如何优雅的停止一个线程?
文章插图
在之前的文章中 i-code.online -《并发编程-线程基础》我们介绍了线程的创建和终止 , 从源码的角度去理解了其中的细节 , 那么现在如果面试有人问你 “如何优雅的停止一个线程?” ,你该如何去回答尼 ?能不能完美的回答尼?
- 对于线程的停止 , 通常情况下我们是不会去手动去停止的 , 而是等待线程自然运行至结束停止 , 但是在我们实际开发中 , 会有很多情况中我们是需要提前去手动来停止线程 , 比如程序中出现异常错误 , 比如使用者关闭程序等情况中 。 在这些场景下如果不能很好地停止线程那么就会导致各种问题 , 所以正确的停止程序是非常的重要的 。
- 在我们平时的开发中我们很多时候都不会注意线程是否是健壮的 , 是否能优雅的停止 , 很多情况下都是贸然的强制停止正在运行的线程 , 这样可能会造成一些安全问题 , 为了避免造成这种损失 , 我们应该给与线程适当的时间来处理完当前线程的收尾工作 ,而不至于影响我们的业务 。
- 对于 Java 而言 , 最正确的停止线程的方式是使用
interrupt
。 但interrupt
仅仅起到通知被停止线程的作用 。 而对于被停止的线程而言 , 它拥有完全的自主权 , 它既可以选择立即停止 , 也可以选择一段时间后停止 , 也可以选择压根不停止 。 可能很多同学会疑惑 , 既然这样那这个存在的意义有什么尼 , 其实对于Java
而言 , 期望程序之间是能够相互通知、协作的管理线程
- 比如我们有线程在进行
io
操作时 , 当程序正在进行写文件奥做 , 这时候接收到终止线程的信号 , 那么它不会立马停止 , 它会根据自身业务来判断该如何处理 , 是将整个文件写入成功后在停止还是不停止等都取决于被通知线程的处理 。 如果这里立马终止线程就可能造成数据的不完整性 , 这是我们业务所不希望的结果 。
- 关于
interrupt
的使用我们不在这里过多阐述 , 可以看 i-code.online -《并发编程-线程基础》文中的介绍 , 其核心就是通过调用线程的isInterrupt()
方法进而判断中断信号 , 当线程检测到为true
时则说明接收到终止信号 , 此时我们需要做相应的处理
- 我们编写一个简单例子来看
Thread thread = new Thread(() -> {while (true) {//判断当前线程是否中断 ,if (Thread.currentThread().isInterrupted()) {System.out.println("线程1 接收到中断信息 , 中断线程...中断标记:" + Thread.currentThread().isInterrupted());//跳出循环 , 结束线程break;}System.out.println(Thread.currentThread().getName() + "线程正在执行...");}}, "interrupt-1");//启动线程 1thread.start();//创建 interrupt-2 线程new Thread(() -> {int i = 0;while (i <20){System.out.println(Thread.currentThread().getName()+"线程正在执行...");if (i == 8){System.out.println("设置线程中断...." );//通知线程1 设置中断通知thread.interrupt();}i ++;try {TimeUnit.MILLISECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}},"interrupt-2").start();
上述代码相对比较简单 , 我们创建了两个线程 , 第一个线程我们其中做了中断信号检测 , 当接收到中断请求则结束循环 , 自然的终止线程 , 在线程二中 , 我们模拟当执行到i==8
时通知线程一终止 , 这种情况下我们可以看到程序自然的进行的终止 。
sleep
时 , 线程能否感受到中断信号?- 对于这一特殊情况 , 我们可以将上述代码稍微修改即可进行验证 , 我们将线程1的代码中加入
sleep
同时让睡眠时间加长 , 让正好线程2通知时线程1还处于睡眠状态 , 此时观察是否能感受到中断信号
//创建 interrupt-1 线程Thread thread = new Thread(() -> {while (true) {//判断当前线程是否中断 ,if (Thread.currentThread().isInterrupted()) {System.out.println("线程1 接收到中断信息 , 中断线程...中断标记:" + Thread.currentThread().isInterrupted());Thread.interrupted(); // //对线程进行复位 , 由 true 变成 falseSystem.out.println("经过 Thread.interrupted() 复位后 , 中断标记:" + Thread.currentThread().isInterrupted());//再次判断是否中断 , 如果是则退出线程if (Thread.currentThread().isInterrupted()) {break;}break;}System.out.println(Thread.currentThread().getName() + "线程正在执行...");try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}}}, "interrupt-1");
- 小米科技|性价比拉满!TCL T8E-PRO QLED智屏当属潮玩世代的必备单品
- 华为鸿蒙系统|华为汽车战略布局,进入汽车行业的底气来自哪里?(车车佳)
- 抖音|抖音如何获取更多流量?一文读懂直播自然流量提升技巧
- 浙江省|浙江的五大富豪,四位做过中国首富,仅马云的阿里就1年纳税366亿
- iOS|恒创科技:Linux日本云服务器安全设置的基本步骤
- javascript|手机移动端的PyTorch来了,还支持JavaScript
- 中关村|柳传志在这里被骗、掘金,书写半部科技史的中关村经历了什么?
- 手机维修|手机维修的猫腻‖你是不是上当了?
- 智能化|感知局限下,车路协同的“子弹”还得再飞会儿
- 华为鸿蒙系统|都2021年底了,为何Mate40Pro还是目前公认最好用的“安卓”手机