Interrupted Exception异常可能没你想的那么简单!
摘要: 当我们在调用Java对象的wait()方法或者线程的sleep()方法时,需要捕获并处理InterruptedException异常。如果我们对InterruptedException异常处理不当,则会发生我们意想不到的后果!
本文分享自华为云社区《【高并发】由InterruptedException异常引发的思考》,作者:冰 河。
前言
当我们在调用Java对象的wait()方法或者线程的sleep()方法时,需要捕获并处理Interrupted Exception异常。如果我们对Interrupted Exception异常处理不当,则会发生我们意想不到的后果!
程序案例
例如,下面的程序代码,Interrupted Task类实现了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 Interrupted Task implements Runnable{@Overridepublic void run() {Thread currentThread = Thread.currentThread();while (true){if(currentThread.isInterrupted()){break;}try {Thread.sleep(100);} catch (Interrupted Exception e) {e.printStack Trace();}}}
}
上述代码的本意是通过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()方法来中断执行线程时,大概率的会触发Interrupted Exception异常,在触发Interrupted Exception异常的同时,JVM会同时把线程的中断标志位清除,所以,这个时候在run()方法中判断的current Thread.isInterrupted()会返回false,也就不会退出当前while循环了。
既然问题分析清除了,那如何中断线程并退出程序呢?
问题解决
正确的处理方式应该是在Interrupted Task类中的run()方法中的while(true)循环中捕获异常之后重新设置中断标志位,所以,正确的Interrupted Task类的代码如下所示。
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();}}}
}
可以看到,我们在捕获Interrupted Exception异常的catch代码块中新增了一行代码。
currentThread.interrupt();
这就使得我们捕获到Interrupted Exception异常后,能够重新设置线程的中断标志位,从而中断当前执行的线程。
我们再次运行Interrupted Test类的main方法,如下所示。
总结
处理Interrupted Exception异常时要小心,如果在调用执行线程的interrupt()方法中断执行线程时,抛出了Interrupted Exception异常,则在触发Interrupted Exception异常的同时,JVM会同时把执行线程的中断标志位清除,此时调用执行线程的isInterrupted()方法时,会返回false。此时,正确的处理方式是在执行线程的run()方法中捕获到Interrupted Exception异常,并重新设置中断标志位(也就是在捕获Interrupted Exception异常的catch代码块中,重新调用当前线程的interrupt()方法)。
点击关注,第一时间了解华为云新鲜技术~
Interrupted Exception异常可能没你想的那么简单!相关推荐
- 《魂斗罗:归来》手游子弹中没中,没你想得那么简单!
无数玩家童年的神作重新回归,手机端多人联机,呼朋引伴一起重温当年的热血大作. 除了IP,剧情,对工程师而言,<魂斗罗:归来>更要解决的联机同步和命中同步等问题,简单说,一颗子弹打没打中,没 ...
- 实锤!Python 真没你想的那么简单…
首先我不可否认,Python确实很"火"!很多开发者都把它当做主语言或是第二语言. 当做主语言原因很好理解,因为最近几年它在人工智能.数据分析.Web开发等众多领域都有着非常成熟的 ...
- 《魂斗罗:归来》子弹中没中,没你想得那么简单!
无数玩家童年的神作重新回归,手机端多人联机,呼朋引伴一起重温当年的热血大作.除了IP,剧情,对工程师而言,<魂斗罗:归来>更要解决的联机同步和命中同步等问题,简单说,一颗子弹打没打中,没你 ...
- set 有序吗js_JavaScript Set没你想的那么简单!
原标题:JavaScript Set没你想的那么简单! 来源 | blog.greenroots.info 译者 | 鬼哥 在本文中,我们将学习Set,并且使用几个小例子来彻底掌握Set,进来的小伙伴 ...
- 大公司为什么都有API网关?没你想的那么简单!
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:rrd.me/g6eyJ 在这篇文章中将我们一起来探讨当前的 ...
- 分页缓冲池如何关闭_线程池没你想的那么简单
前言 原以为线程池还挺简单的(平时常用,也分析过原理),这次是想自己动手写一个线程池来更加深入的了解它:但在动手写的过程中落地到细节时发现并没想的那么容易.结合源码对比后确实不得不佩服 Doug Le ...
- 天赋 VS 勤奋,“一万小时定律” 没你想得那么简单
(文/马尔科姆·格拉德威尔)40年前,赫伯特· 西蒙(Herbert Simon)和威廉·蔡斯(William Chase) 在美国科学家杂志上刊登了一篇论文,在研究专业知识方面得出一个著名结论: & ...
- 【Python】Python中的for循环,没你想的那么简单~
公众号:尤而小屋 作者:Peter 编辑:Peter 一年四季,循环往复:说到底就是一个循环的问题 for语句实际上解决的是循环问题.在很多的高级语言中都有for循环(for loop). for语句 ...
- 怎么把字符串变成数组_Java中字符串split() 的使用方法,没你想的那么简单
先看下面的方法,事先预测一下,经过split方法,按逗号进行分割为数组之后,生成的数组的长度是多少,目测很多人都觉得是8,但是结果却出乎意料.是5而不是8. private static void t ...
最新文章
- Linux下查看显示器输出状态以及修改显示器工作模式(复制 or 扩展)
- JQuery:JQuery 中的CSS()方法
- 无人机数车--Drone-based Object Counting by Spatially Regularized Regional Proposal Network
- opensuse13.2 安裝五笔
- 计算机学院大学生程序设计竞赛(2015’11)1007 油菜花王国
- Qt学习笔记之常用控件QTreeWidget
- 站覆盖范围_武汉高铁站落地灯箱广告有什么投放价值?
- 阿里云终端连接与实例管理
- 自动语音识别的原理是什么,它的作用是什么
- cdq分治 陌上花开(内无题解)
- 程序员入门必备经典书单
- c++语言坦克大战源代码,C++代码之坦克大战(1)(示例代码)
- 「面试必背」Linux面试题(2022最新版)
- 使用xshell连接阿里云服务器【最近版、无坑系列】
- 利用U盘引导进入pe系统修复操作系统
- python用Selenium爬取携程网机票信息
- python中reduce是什么意思_Python----reduce原来是这样用的
- [置顶]CHENEY-YANG'S BLOG(cheney-yang)
- 2022-03-13-Redis
- 苹果系统中英文输入法切换_Mac系统,如何优雅切换中英文?
热门文章
- LeetCode 312. 戳气球(Burst Balloons)
- Spring Boot入门系列(十六)整合pagehelper,一秒实现分页功能!
- Python 中的json字符串以及使用
- adfs服务器获取信息失败,在ADFS服务器上SAML LogOutRequest处理失败
- C语言里面双分号是啥意思,问什么C程序里总是提示缺少分号;,而明明有分号?...
- java 双声道音频_Android 播放音频如何实现双声道效果
- python面试题_01
- Codeforces | CF1029F 【Multicolored Markers】
- 图的深度优先搜索(DFS)和广度优先搜索(BFS)算法
- Struts2中的图片验证码