线程
2025-01-22 08:19:30 1.2k 字
This post is also available in English and alternative languages.
线程是一个操作系统级别的概念。Java语言(包括其他编程语言)本身不创建线程;而是调用操作系统层提供的接口创建、控制、销毁线程实例。
不同的操作系统(Windows/Unix/Linux/其他),它们所支持的线程底层实现和操作效果也是不尽相同的;不过一个操作系统支持的线程至少会有四种状态:就绪、执行、阻塞和终结。线程在四种状态下进行切换,都是要消耗不少的CPU计算能力的。
线程还分为用户线程和操作系统线程:
- 操作系统线程(内核线程),是指操作系统内核为了完成硬件接口层操作,由操作系统内核创建的线程:例如I/O操作的内核线程,这些线程应用程序是不能干预的
- 用户线程,是指用户安装/管理的应用程序,为执行某一种操作,而由这个应用程序创建的线程(Java线程,都是用户级线程)。
sleep将“当前线程”进入阻塞状态,并且不会释放这个线程所占用的任何对象锁的独占状态。
1. 线程中断
1.1. interrupt相关方法
结论先行:单纯用 interrupt()
方法并不能中断(停止)当前正在运行的线程,需要配合其他方法才能正确中断(停止)线程。
Thread.currentThread().interrupt()
:设置线程中断(停止)标识;Thread.interrupted()
:判断线程的中断(停止)标识。
如果使用interrupt
方法只是设置线程的中断(停止)标识,线程内部需要手动判断标识(interrupted
方法),组合使用才能中断(停止)线程的处理;
如果只调用interrupt
方法,是不会起到中断(停止)线程的目的。
只调用
interrupt
方法,不会起到中断(停止)线程的目的1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26/**
* @author yxcheng
*/
public class TestApp {
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 200000; i++) {
log.info("threadName:[{}],i:[{}]", Thread.currentThread().getName(), i);
}
});
thread1.start();
TimeUnit.MILLISECONDS.sleep(500);
//设置 thread1 的中断(停止)标识
thread1.interrupt();
//等待 thread1 执行结束
thread1.join();
log.warn("----- end -----");
}
}运行结果:
1
2
3
42022-07-07 14:08:45.853 default [Thread-0] INFO org.concurrent.demo01.TestApp - 22 - threadName:[Thread-0],i:[199997]
2022-07-07 14:08:45.853 default [Thread-0] INFO org.concurrent.demo01.TestApp - 22 - threadName:[Thread-0],i:[199998]
2022-07-07 14:08:45.853 default [Thread-0] INFO org.concurrent.demo01.TestApp - 22 - threadName:[Thread-0],i:[199999]
2022-07-07 14:08:45.853 default [main] WARN org.concurrent.demo01.TestApp - 36 - ----- end -----interrupt
、interrupted
两个方法,组合使用中断(停止)处理1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27/**
* @author yxcheng
*/
public class TestApp {
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(() -> {
// for循环,循环时判断thread1的中断(停止)标识
for (int i = 0; !Thread.currentThread().isInterrupted() && i < 200000; i++) {
log.info("threadName:[{}],i:[{}]", Thread.currentThread().getName(), i);
}
});
thread1.start();
TimeUnit.MILLISECONDS.sleep(500);
//设置 thread1 的中断(停止)标识
thread1.interrupt();
//等待 thread1 执行结束
thread1.join();
log.warn("----- end -----");
}
}运行结果:
1
2
3
4
5........
2022-07-07 14:07:12.048 default [Thread-0] INFO org.concurrent.demo01.TestApp - 18 - threadName:[Thread-0],i:[24103]
2022-07-07 14:07:12.048 default [Thread-0] INFO org.concurrent.demo01.TestApp - 18 - threadName:[Thread-0],i:[24104]
2022-07-07 14:07:12.048 default [Thread-0] INFO org.concurrent.demo01.TestApp - 18 - threadName:[Thread-0],i:[24105]
2022-07-07 14:07:12.049 default [main] WARN org.concurrent.demo01.TestApp - 36 - ----- end -----
2. 线程阻塞
通过LockSupport#park
和LockSupport#unpark
方法配合使用,可以让线程暂停、恢复。
- LockSupport#park:阻塞(暂停)线程
- `LockSupport#unpark:唤醒(恢复)线程
1 | /** |
运行结果:
1 | 2022-07-07 14:55:26.623 default [Thread-0] INFO org.concurrent.demo01.TestApp - 17 - 线程:[Thread-0],开始执行 |