摘要:我们就以一个案例的形式,来为大家详细介绍下为何中断执行的线程不起作用。

本文分享自华为云社区《明明中断了线程,却为何不起作用呢?》,作者:冰 河。

当我们在调用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的更多相关文章

  1. Java 如何中断和恢复线程的执行

    一.线程的状态 线程可以阻塞于四种状态: 1.当线程执行Thread.sleep()时,它一直阻塞到指定的毫秒时间之后,或者阻塞被另一个线程打断: 2.当线程碰到一条wait()语句时,它会一直阻塞到 ...

  2. java线程中断和终止线程运行

    ava中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线程 ...

  3. 《Java并发编程》之线程中断与终止线程运行

    Java中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线 ...

  4. 多线程之旅(9)_如何安全的取消正在执行的线程——附C#源码

    参考网址: https://blog.csdn.net/yangwohenmai1/article/details/90404497 当线程能流畅安全的自动运行后,我们就要考虑一些更风骚的操作,就是如 ...

  5. python任务执行之线程,进程,与协程

    一.线程 线程为程序中执行任务的最小单元,由Threading模块提供了相关操作,线程适合于IO操作密集的情况下使用 #!/usr/bin/env python # -*- coding:utf-8 ...

  6. C# 多线程join的用法,等待多个子线程结束后再执行主线程

    等待多个子线程结束后再执行主线程 class MultiThread{ #region join test public void MultiThreadTest() { Thread[] ths = ...

  7. 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法

    [源码下载] 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法 作者:webabcd 介绍重新想象 Wi ...

  8. 查看MySQL正在执行的线程

    一.使用SQL语句查询正在执行的线程 SHOW PROCESSLIST; 二.使用kill 线程id就可以结束线程(引起数据变化的线程需特别小心) SHOW PROCESSLIST; +------+ ...

  9. 浅谈线程池(中):独立线程池的作用及IO线程池

    原文地址:http://blog.zhaojie.me/2009/07/thread-pool-2-dedicate-pool-and-io-pool.html 在上一篇文章中,我们简单讨论了线程池的 ...

随机推荐

  1. Android命令行启动模拟器

    我们在平时的开发中会经常需要使用模拟器进行调试,这个时候我们就要先打开Android Studio来启动模拟器,然后再运行App.这个流程中启动Android Studio需要花费一些时间,而模拟器的 ...

  2. 推荐一个pycharm验证xpath表达式的插件XPathView +​ XSLT

    使用Appium进行自动化测试,使用xpath元素定位,想验证xpath定位是否正确,可以使用在线的xpath验证网站,也可以使用这次推荐的插件XPathView +​ XSLT.

  3. ios web 媒体查询兼容

    原文:https://blog.csdn.net/dear_zx/article/details/82785250 防止链接丢失,复制一下 兼容iphone4/4s: @media (device-h ...

  4. 利用griddata进行二维插值

    有时候会碰到这种情况: 实际问题可以抽象为 \(z = f(x, y)\) 的形式,而你只知道有限的点 \((x_i,y_i,z_i)\),你又需要局部的全数据,这时你就需要插值,一维的插值方法网上很 ...

  5. python3.7+flask+alipay 支付宝付款功能

    文档参考github:https://github.com/fzlee/alipay/blob/master/docs/init.md 沙箱环境配置:https://opendocs.alipay.c ...

  6. P4606-[SDOI2018]战略游戏【圆方树,虚树】

    正题 题目链接:https://www.luogu.com.cn/problem/P4606 题目大意 给出\(n\)个点\(m\)条边的一张图,\(q\)次询问给出一个点集,询问有多少个点割掉后可以 ...

  7. Digital Image Processing

    20190919 Review CCD:高端天文学,敏感度高,速度慢,成本高: CMOS:普遍使用,嵌入手机,速度快,有模式噪声(Pattern Noise,现在可以解决): 空间分辨率和时间分辨率: ...

  8. iOS 15 无法弹出授权弹框之解决方案---Your app uses the AppTrackingTransparency framework, but we are unable to locate the App Tracking Transparency permission request when reviewed on iOS 15.0

    2021年9月30日下午:我正愉快的期盼着即将到来的国庆假期,时不时刷新下appstoreconnect的网址,28号就提上去的包,今天还在审核中....由于这个版本刚升级的xcode系统和新出的iO ...

  9. feign的一个注解居然隐藏这么多知识!

    引言 最近由于业务的需要,需要接入下阿里云的一个接口,打开文档看了看这个接口看下来还是比简单的目测个把小时就可以搞定,但是接入的过程还是比较坎坷的.首先我看了看他给的示例,首先把阿里云文档推荐的dem ...

  10. 2019 年 CNCF 中国云原生调查报告

    中国 72% 的受访者生产中使用 Kubernetes 在 CNCF,为更好地了解开源和云原生技术的使用,我们定期调查社区.这是第三次中国云原生调查,以中文进行,以便更深入地了解中国云原生技术采用的步 ...