不能靠 thread.stop() 强制终止,应采用协作式退出:用 volatile 标志位控制循环,配合 interrupt() 唤醒阻塞线程,并以标志位与 isinterrupted() 双重校验确保安全停止。

不能靠 Thread.stop() 强制终止,它已被废弃多年,会直接释放锁、中断 I/O、跳过 finally 清理,极易导致数据损坏或资源泄漏。安全停止的核心是“协作式退出”:让子线程自己感知停止信号,并在合适时机主动结束。
用 volatile 标志位控制循环执行
这是最基础也最常用的方案,适用于纯计算或非阻塞任务。
- 定义一个
private volatile boolean running = true;字段,volatile保证主线程修改后,子线程能立即看到新值 - 循环体必须始终检查该标志,例如
while (running) { ... } - 提供外部可调用的
shutdown()方法,设running = false - 循环内若有耗时操作(如
Thread.sleep()),需包裹在try-catch(InterruptedException)中,并恢复中断状态
遇到阻塞调用时必须配合 interrupt()
仅靠标志位无法唤醒正在 BlockingQueue.take()、Object.wait()、ServerSocket.accept() 等处挂起的线程。
- 调用
thread.interrupt()可触发InterruptedException,打断多数标准阻塞方法 - 捕获异常后,务必执行
Thread.currentThread().interrupt()—— 否则中断状态丢失,上层逻辑可能误判 - 推荐改用带超时的非阻塞替代方案,例如用
queue.poll(100, TimeUnit.MILLISECONDS)替代take(),这样既能响应中断,又能定期检查标志位
标志位 + 中断状态双重校验更健壮
把两种机制结合,覆盖运行中和阻塞中的所有场景。
- 循环条件写成
while (running && !Thread.currentThread().isInterrupted()) - 即使某次未捕获到中断(比如没发生阻塞),也能靠标志位退出;一旦发生阻塞,中断又能及时唤醒
- 退出前统一执行清理逻辑(关闭文件、释放连接、提交事务等),放在循环外、
run()方法末尾
避免常见陷阱
很多看似合理的写法实际存在隐患。
- 不用
static或非volatile布尔变量——JVM 可能缓存旧值,子线程永远读不到变化 - 不要在循环外检查标志位,比如先判断再执行一大段逻辑——这会导致“已通知停止,但还在干完手头活”
- 别忽略
InterruptedException,更不要只打印日志就继续循环——这等于屏蔽中断信号 -
Thread.interrupted()是静态方法,会清空中断状态;日常校验优先用实例方法isInterrupted()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











