主题切换
停止运行线程
一、三种停止线程方式
- 自定义布尔退出标记 设置volatile布尔变量,循环内判断标记,满足条件退出run方法,线程正常结束。安全优雅,业务可控。
- Thread.stop()(废弃,禁止使用) 强制杀死线程,直接释放锁,会造成数据错乱、资源未释放、事务中断,JDK标记废弃。
- interrupt() 中断标记法(主流推荐) 仅设置线程中断状态,不会直接杀死线程,分阻塞线程、运行中线程两种逻辑。
二、interrupt 详细原理
1. 核心本质
interrupt() 只是给线程打上中断标记,不会立刻终止线程,由线程自身代码判断标记自主退出。 配套方法:
thread.interrupt():设置中断标记为trueThread.isInterrupted():获取当前线程中断标记,不清除标记Thread.interrupted():静态方法,获取标记并清除中断标记
2. 两种场景处理逻辑
1)线程处于阻塞状态(sleep / wait / join) 调用interrupt后,线程立刻抛出InterruptedException,同时自动清除中断标记; 捕获异常后可主动跳出循环结束线程。
2)线程正常运行、无阻塞 interrupt仅修改中断标记为true,不会抛异常; 业务代码循环中通过isInterrupted()判断标记,主动return退出。
3. 优势
完全交给业务代码控制退出时机,能收尾资源、提交/回滚事务,不会出现stop()的数据安全问题。
三、面试高频问题解析
问:Java有哪些停止线程的方式?
答: 三种。第一,自定义volatile布尔标识,正常走完run方法退出;第二,调用stop()强制终止,已废弃不推荐;第三,使用interrupt()设置中断标记,线程自行判断标记退出,是项目主流方案。
问:interrupt()会直接杀死线程吗?
答: 不会。interrupt仅修改线程内部中断状态标记,不会直接终止线程;只有线程代码主动检测该标记,或线程处于sleep/wait/join阻塞时抛出异常,才能结束线程。
问:sleep的线程调用interrupt会发生什么?
答: 线程立即退出阻塞,抛出InterruptedException,同时清空线程的中断标记,需要在catch块中手动跳出循环终止任务。
问:isInterrupted()和interrupted()有什么区别?
答: isInterrupted()是实例方法,仅读取中断标记,不会重置状态;interrupted()是静态方法,读取标记后会把中断状态重置为false。
问:为什么不推荐使用Thread.stop()?
答: stop会强行终止线程,不执行收尾逻辑,直接释放同步锁,极易导致共享数据损坏、文件/连接资源未关闭、事务中途中断,存在严重并发安全问题,JDK已废弃。