为何我中断执行的线程不起作用,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{ @Override
public 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{ @Override
public 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的更多相关文章
- Java 如何中断和恢复线程的执行
一.线程的状态 线程可以阻塞于四种状态: 1.当线程执行Thread.sleep()时,它一直阻塞到指定的毫秒时间之后,或者阻塞被另一个线程打断: 2.当线程碰到一条wait()语句时,它会一直阻塞到 ...
- java线程中断和终止线程运行
ava中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线程 ...
- 《Java并发编程》之线程中断与终止线程运行
Java中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线 ...
- 多线程之旅(9)_如何安全的取消正在执行的线程——附C#源码
参考网址: https://blog.csdn.net/yangwohenmai1/article/details/90404497 当线程能流畅安全的自动运行后,我们就要考虑一些更风骚的操作,就是如 ...
- python任务执行之线程,进程,与协程
一.线程 线程为程序中执行任务的最小单元,由Threading模块提供了相关操作,线程适合于IO操作密集的情况下使用 #!/usr/bin/env python # -*- coding:utf-8 ...
- C# 多线程join的用法,等待多个子线程结束后再执行主线程
等待多个子线程结束后再执行主线程 class MultiThread{ #region join test public void MultiThreadTest() { Thread[] ths = ...
- 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法
[源码下载] 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法 作者:webabcd 介绍重新想象 Wi ...
- 查看MySQL正在执行的线程
一.使用SQL语句查询正在执行的线程 SHOW PROCESSLIST; 二.使用kill 线程id就可以结束线程(引起数据变化的线程需特别小心) SHOW PROCESSLIST; +------+ ...
- 浅谈线程池(中):独立线程池的作用及IO线程池
原文地址:http://blog.zhaojie.me/2009/07/thread-pool-2-dedicate-pool-and-io-pool.html 在上一篇文章中,我们简单讨论了线程池的 ...
随机推荐
- jmeter如何确定ramp-up时间
原文来自:https://www.cnblogs.com/hjhsysu/p/9189897.html 线程属性包含了:线程数.Ramp-Up时间(秒).循环次数. 我整理下线程属性的定义,如图: 难 ...
- file_get_contents('php://input') 数据如何转换成数组
前台表单页:demo01.html 后台:demo01.php 输出结果: 备注:若前台通过Ajax的post提交过来的是json数据,需要对json数据进行解析:$data = json_decod ...
- LR虚拟用户已设置集合点,但controller无法设置集合点策略的解决方案
原文来自:https://blog.csdn.net/qq_34982914/article/details/90905030 学习loadrunner的过程中,肯定涉及集合点的添加,但是我们按照书上 ...
- 定要过python二级 选择题第四套
1. 2. 3. 4. 5. 6. python用于人工智能 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
- String(char[] value, boolean share) {
记录一下今天被蠢到 1. 在观察StringBuffer类的toString方法时,发现了个没见过的方法 return new String(toStringCache, true); @Overri ...
- windows下编译caffe出现错误 C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe?
解决方案来自http://blog.csdn.net/u012556077/article/details/50353818
- 从零入门 Serverless | 一文搞懂函数计算及其工作原理
作者 | 孔德慧(夏莞) 阿里云函数计算开发工程师 什么是函数计算 大家都了解,Serverless 并不是没有服务器,而是开发者不再需要关心服务器.下图是一个应用从开发到上线的对比图: 在传统 Se ...
- 15-ThreadLocalRandom类剖析
ThraedLocalRandom类是JDK7在JUC包下新增的随机数生成器,它弥补了Random类在多线程下的缺陷. Random类及其缺陷 下面看一下java.util.Random的使用方法. ...
- PTA实验11-1-7 藏头诗 (15分)
实验11-1-7 藏头诗 (15分) 本题要求编写一个解密藏头诗的程序. 输入格式: 输入为一首中文藏头诗,一共四句,每句一行.注意:一个汉字占两个字节. 输出格式: 取出每句的第一个汉字并连接在一起 ...
- netty系列之:让TLS支持http2
目录 简介 TLS的扩展协议NPN和ALPN SslProvider ApplicationProtocolConfig 构建SslContext ProtocolNegotiationHandler ...