1. 核心概念简述
在 Java 中,中断(Interrupt)是一种协作机制,而不是强制命令。调用 thread.interrupt() 并不会立即停止目标线程的运行,它仅仅是把目标线程的中断标志位设置为 true。目标线程需要自己去检测这个标志位,并决定如何响应(通常是清理资源后退出)。
2. 原理与源码关键点
三个关键方法
interrupt():设置中断标志位。如果线程处于阻塞状态(如sleep,wait),会抛出InterruptedException并清除标志位。isInterrupted():查询当前中断标志位,不改变状态。Thread.interrupted():静态方法,查询当前线程的中断标志位,并重置(清除)该标志位。
为什么不能用 stop()?
Thread.stop() 方法已被废弃。因为它太暴力,会立即终止线程并释放该线程持有的所有锁(Monitors)。这可能导致受保护的数据处于不一致的状态(例如转账转了一半),从而破坏数据完整性。
3. 最佳实践
场景一:循环任务
在循环条件中显式检查中断标志。
while (!Thread.currentThread().isInterrupted()) {
// 执行任务
}
场景二:处理 InterruptedException
这是面试中的高频考点。当捕获到 InterruptedException 时,标志位会被自动清除。如果你不打算抛出该异常,必须手动再次中断当前线程,以恢复中断状态,否则上层调用者无法感知线程已被中断。
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// 错误做法:打印日志后什么都不做(吞掉中断)
// e.printStackTrace();
// 正确做法:恢复中断状态
Thread.currentThread().interrupt();
// 或者:抛出异常 throw e;
}
4. 总结与示例
回答总结: “安全中断线程必须使用 interrupt() 协作机制,坚决避免使用废弃的 stop()。线程内部应通过 isInterrupted() 轮询标志位。如果捕获了 InterruptedException,由于异常抛出时会清除标志位,必须在 catch 块中调用 Thread.currentThread().interrupt() 恢复中断状态,或者直接抛出异常,确保中断信号能传递给上层。”