JDK 推荐的线程关闭方式
-
任务执行完成,或异常终止,任务认为无需再占用线程。 -
线程池根据当前任务执行情况,伸缩线程池。当任务执行较少时,退出空闲的线程。 -
服务或进程在关闭阶段,例如滚动发布时,需要退出线程、关闭线程池、关闭进程。 -
定时任务、周期任务需要终止执行时,需要退出当前线程。或者退出当前任务的执行。
优雅关闭Or强行关闭
标题 | 好处 | 坏处 |
---|---|---|
优雅关闭(主动通知线程关闭) | 能优雅退出线程,保证资源被释放,保证处理中请求正确被处理完成 | 无法立即关闭线程,执行中的任务不响应关闭信号,拒绝关闭线程 |
强行关闭线程 | 可以立刻关闭线程 | 存在资源未释放、处理中请求异常中断,例如分布式锁漏释放。写流程异常中断,数据不一致,重试也无法恢复 |
Thread.stop() 这种方法本身就是不安全的,Stop一个线程会随之解锁这个线程所持有的监视器(可以理解为锁),如果受这些监视器(锁)保护的临界对象处在不一致状态,则其他线程可能会看到这些对象处于不一致状态,那么将导致未知的行为。对Thread.Stop()的调用应该被简单的代码代替,例如 修改一个变量,目标线程定期检查这个变量,有序从run 方法return出来。如果目标线程在一个条件变量上wait,则其他线程应该使用interrupt方法中断目标线程。
业务字段标记
while(config.isTaskEnable()){//从配置中心获取任务是否要终止
//循环执行业务逻辑。直到执行完成退出,或者被终止。
}
Thread.interrupt()
JDK: 如果目标线程在一个条件变量上wait,则其他线程应该使用interrupt方法中断目标线程。
如果其他线程调用目标线程的interrupt方法,
恰好目标线程在调用. Object.wait(),object.join(),Object.sleep()等方法时,目标线程的中断位标记被清除,同时目标线程会立即从sleep、wait等调用中恢复,并且被抛出InterruptException。 如果目标线程在IO操作中被阻塞,例如io.channels.InterruptibleChannel,Channel将被关闭,线程的中断位被设置,同时目标线程收到java.nio.channels.ClosedByInterruptException。 如果目标线程被阻塞在java.nio.channels.Selector,线程中断状态被设置,然后目标线程立即从select中返回非零值。 如果其他条件都不成立,该线程中断位会被设置。
Thread.isInterrupted
方法查看当前是否处于中断位?那为什么目标线程阻塞在Object.wait(),Sleep()方法时,抛出了interruptException,会取消标记呢?实际上interrupt操作执行两件事,推荐一个非常好的博客 通过JVM源码分析 interrupt和sleep的实现原理。
推荐的中断响应策略
立即响应中断
-
目标线程的任务在InterruptedException异常处理中,要主动回收资源,打印日志,退出任务执行。 -
目标线程如果没有阻塞操作,例如sleep、wait。可以通过 Thread.isInterrupted(),查看当前中断位状态,如果被中断了,则采取以上第一步操作。
忽略中断,交给上一层处理
-
抛出InterruptedException给上层,由上层代码处理。 -
调用Thread.interrupt()。重新设置中断位标记(自己中断自己)。由上游代码在本层方法返回后,检查中断位标记,进行中断处理。
千万不要吞掉中断
for (int i = 0; i < cnt; i++) {
try {
//执行业务逻辑
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println(“被中断”);
}
System.out.println(“子线程执行中”);
}
while(true){
callChildMethod();//调用下游方法,但是下游吞掉了中断
if (Thread.currentThread().isInterrupted()) {
//回收资源,退出线程
}
}
-
不推荐强制销毁线程,会导致资源无法被释放,进行中请求无法正常处理完,导致业务数据处于不可知的状态。 -
Java推荐优雅退出线程。 -
业务层可以使用字段标记,定期检查是否需要退出任务。 -
Thread.interrupt中断目标线程、isInterrupted查询中断位标记。 -
使用Thread.interrupt处理中断也可以优雅退出,但需要上下层堆栈都要关注中断,不得吞掉中断。
微信赞赏
支付宝扫码领红包
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。侵权投诉:375170667@qq.com