为何我中断执行的线程不起作用,Why
摘要:我们就以一个案例的形式,来为大家详细介绍下为何中断执行的线程不起作用。
本文分享自华为云社区《明明中断了线程,却为何不起作用呢?》,作者:冰 河。
当我们在调用Java对象的wait()方法或者线程的sleep()方法时,需要捕获并处理Interrupted Exception异常。如果我们对Interrupted Exception异常处理不当,则会发生我们意想不到的后果!今天,我们就以一个案例的形式,来为大家详细介绍下为何中断执行的线程不起作用。
程序案例
例如,下面的程序代码,InterruptedTask类实现了Runnable接口,在run()方法中,获取当前线程的句柄,并在while(true)循环中,通过isInterrupted()方法来检测当前线程是否被中断,如果当前线程被中断就退出while(true)循环,同时,在while(true)循环中,还有一行Thread.sleep(100)代码,并捕获了Interrupted Exception异常。整个代码如下所示。
package io.binghe.concurrent.lab08;/*** @author binghe* @version 1.0.0* @description 线程测试中断*/
public class InterruptedTask implements Runnable{@Overridepublic void run() {Thread currentThread = Thread.currentThread();while (true){if(currentThread.isInterrupted()){break;}try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}
}
上述代码的本意是通过isInterrupted()方法检查线程是否被中断了,如果中断了就退出while循环。其他线程通过调用执行线程的interrupt()方法来中断执行线程,此时会设置执行线程的中断标志位,从而使currentThread.isInterrupted()返回true,这样就能够退出while循环。
这看上去没啥问题啊!但真的是这样吗?我们创建一个Interrupted Test类用于测试,代码如下所示。
package io.binghe.concurrent.lab08;/*** @author binghe* @version 1.0.0* @description 测试线程中断*/
public class InterruptedTest {public static void main(String[] args){InterruptedTask interruptedTask = new InterruptedTask();Thread interruptedThread = new Thread(interruptedTask);interruptedThread.start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}interruptedThread.interrupt();}
}
我们运行main方法,如下所示。
这竟然跟我们想象的不一样!不一样!不一样!这是为什么呢?
问题分析
上述代码明明调用了线程的interrupt()方法来中断线程,但是却并没有起到啥作用。原因是线程的run()方法在执行的时候,大部分时间都是阻塞在sleep(100)上,当其他线程通过调用执行线程的interrupt()方法来中断执行线程时,大概率的会触发InterruptedException异常,在触发InterruptedException异常的同时,JVM会同时把线程的中断标志位清除,所以,这个时候在run()方法中判断的currentThread.isInterrupted()会返回false,也就不会退出当前while循环了。
既然问题分析清除了,那如何中断线程并退出程序呢?
问题解决
正确的处理方式应该是在InterruptedTask类中的run()方法中的while(true)循环中捕获异常之后重新设置中断标志位,所以,正确的InterruptedTask类的代码如下所示。
package io.binghe.concurrent.lab08;/*** @author binghe* @version 1.0.0* @description 中断线程测试*/
public class InterruptedTask implements Runnable{@Overridepublic void run() {Thread currentThread = Thread.currentThread();while (true){if(currentThread.isInterrupted()){break;}try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();currentThread.interrupt();}}}
}
可以看到,我们在捕获InterruptedException异常的catch代码块中新增了一行代码。
currentThread.interrupt();
这就使得我们捕获到InterruptedException异常后,能够重新设置线程的中断标志位,从而中断当前执行的线程。
我们再次运行InterruptedTest类的main方法,如下所示。
总结
处理InterruptedException异常时要小心,如果在调用执行线程的interrupt()方法中断执行线程时,抛出了InterruptedException异常,则在触发InterruptedException异常的同时,JVM会同时把执行线程的中断标志位清除,此时调用执行线程的isInterrupted()方法时,会返回false。此时,正确的处理方式是在执行线程的run()方法中捕获到InterruptedException异常,并重新设置中断标志位(也就是在捕获InterruptedException异常的catch代码块中,重新调用当前线程的interrupt()方法)。
点击关注,第一时间了解华为云新鲜技术~
为何我中断执行的线程不起作用,Why相关推荐
- while(true) 循环中使用了sleep休眠了半小时就中断了_线程中断不是你想中断就能的...
为什么不强制停止 如何用 interrupt 停止线程 sleep 期间能否感受到中断 停止线程的方式有几种 总结 启动线程需要调用 Thread 类的 start() 方法,并在 run() 方法中 ...
- 线程池如何保证所有子线程运行完再执行主线程
Java主线程等待所有子线程执行完毕在执行,其实在我们的工作中经常的用到,比如说主线程要返回一个响应用户的值,但这个值得赋值过程是由过个子线程来完成的(模拟一个实际开发的情景),所以主线程必须等待子线 ...
- java线程中断和终止线程运行
ava中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线程 ...
- 有赞一面:还有任务没执行,线程池被关闭怎么办?
说在前面 在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如极兔.有赞.希音的面试资格,遇到一几个很重要的面试题: 还有线程池正在执行的任务和线程,如果线程池shutd ...
- Kotlin的协程,延时、超时(7秒后超时,并中断执行的任务)
Kotlin协程 简介: 优点:写法很简单,轻量级,挂起几乎不消耗内存,速度上优于java的线程,性能损耗小,能大幅度提高并发性能,本人推荐使用协程,而不用传统的线程 GlobalScope是生命周期 ...
- python多线程的使用(导入线程模块、创建子线程任务、启动子线程任务、获取当前执行的线程号)
1. 导入线程模块 #导入线程模块 import threading 2. 线程类Thread参数说明 Thread([group [, target [, name [, args [, kwarg ...
- 【Android 异步操作】Android 线程切换 ( 判定当前线程是否是主线程 | 子线程中执行主线程方法 | 主线程中执行子线程方法 )
文章目录 一.判定当前线程是否是主线程 二.子线程中执行主线程方法 三.主线程中执行子线程方法 一.判定当前线程是否是主线程 在 Android 中 , 如果要判定当前线程是否是主线程 , 可以使用如 ...
- ansible-playbook如何判断并中断执行
今天碰到一个需求,当使用ansible-playbook在执行一个脚本后,根据脚本返回的内容判断是否继续往下执行还是中断执行,查询官网发现使用register寄存器可以实现记录脚本输出,使用when+ ...
- python编程(你的电脑能够执行多少线程和进程)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 对python比较熟悉的同学,相信都写过多线程和多进程的代码.可是,不知道大家有没有这么一个想法 ...
最新文章
- oracle10g索引不生效,oracle 10g分区表索引失效测试
- vscode配置记录
- seaborn可视化散点图并自定义可视化结果图像的大小(Change the Size of a Seaborn Plot)
- if vue 跳出_vue使用v-if v-show 页面闪烁
- Servlet调用流程
- 轻松搞定RabbitMQ(二)——工作队列之消息分发机制
- linux编程问题记录
- 毕业论文word排版设置
- elasticsearch-analysis-ik-1.10.0中文分词插件安装
- xx信息管理系统设计
- IPSEC是如何穿越NAT的
- C++笔记---函数声明(prototype)
- libav(ffmpeg)简明教程(1)
- ASP.NET Ajax 实现无刷新分页
- Java -- Servlet面试题及答案(需更深入了解)
- 摄影后期从入门到精通(一)
- 项目管理手记(七)--DRP系统的文化输出与营销
- 【电蜂优选科普】USB数据线接口有哪些类型呢?
- 如何将前端echats 图表插入到execl 中
- Mac百度云盘不限速操作步骤