interrupted属性
大约 2 分钟
线程的打断标记 (Interrupt Status) 是 Java 线程对象(Thread)内部维护的一个 boolean 类型的状态位。
它的作用更像是一个“消息信箱”或“建议”,而不是强制命令。 当你调用 thread.interrupt() 时,仅仅是将这个标记设为 true。线程本身并不会立即停止运行,如何响应这个“建议”完全取决于线程自己的代码逻辑。
1. 三个核心方法
理解打断标记,必须区分这三个方法:
| 方法 | 静态/实例 | 作用 | 对标记的影响 |
|---|---|---|---|
interrupt() | 实例方法 | 打招呼。给目标线程发送中断信号。 | 将标记设为 true |
isInterrupted() | 实例方法 | 偷看。检查线程的中断状态。 | 不清除标记(状态不变) |
interrupted() | 静态方法 | 查看并消费。检查当前线程的状态。 | 清除标记(重置为 false) |
- 重点:
Thread.interrupted()是唯一能清除标记的方法。它的设计意图是:“我收到这个中断消息了,并且我已经处理了,所以把信箱清空,以免下次误判。”
2. 两种响应场景
场景 A:线程正在睡觉 (Blocked/Waiting)
如果线程正处于阻塞状态(例如调用了 sleep(), wait(), join()),此时如果被打断:
- 线程会立即被唤醒(停止阻塞)。
- 抛出
InterruptedException异常。 - 关键点:打断标记会被自动清除(置为 false)!
- 原理:JVM 认为抛出异常本身就是一种通知机制,既然异常已经抛出来了,说明你已经知道被中断了,所以标记位就不需要保留了。
场景 B:线程正在干活 (Running)
如果线程正在正常运行代码(比如在算数学题):
thread.interrupt()不会对线程产生任何实质影响。它还是继续跑。- 打断标记变为
true。 - 线程代码需要自己去轮询检查这个标记,才能实现中断逻辑:
while (true) { if (Thread.currentThread().isInterrupted()) { // 检查标记 System.out.println("老板叫我停,那我就停吧"); break; // 响应中断,退出循环 } // 继续干活... }
3. AQS 中的处理 (ReentrantLock)
在 AQS 的锁竞争中(lock() 方法),中断处理比较特殊:
- 不响应中断:线程在排队抢锁的过程中,即使被打断了,它也不会抛出异常退出排队,而是继续死皮赖脸地抢锁。
- 记录标记:但是它会用一个局部变量(如
interrupted = true)把这个事儿记下来。 - 事后补发:等到终于抢到锁了,它会调用
selfInterrupt(),再次执行Thread.currentThread().interrupt(),把刚才因为抢锁而被忽略的中断标记重新补上,交给用户业务代码去处理。
总结
打断标记就是一个 boolean 开关。
true:有人想让你停。- 阻塞时被打断:标记清空,抛异常。
- 运行时被打断:标记变 true,除非你自己去查,否则没人管你。
- 静态方法
interrupted():查完就清空(阅后即焚)。