摘要: 当我们在调用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异常可能没你想的那么简单!相关推荐

  1. 《魂斗罗:归来》手游子弹中没中,没你想得那么简单!

    无数玩家童年的神作重新回归,手机端多人联机,呼朋引伴一起重温当年的热血大作. 除了IP,剧情,对工程师而言,<魂斗罗:归来>更要解决的联机同步和命中同步等问题,简单说,一颗子弹打没打中,没 ...

  2. 实锤!Python 真没你想的那么简单…

    首先我不可否认,Python确实很"火"!很多开发者都把它当做主语言或是第二语言. 当做主语言原因很好理解,因为最近几年它在人工智能.数据分析.Web开发等众多领域都有着非常成熟的 ...

  3. 《魂斗罗:归来》子弹中没中,没你想得那么简单!

    无数玩家童年的神作重新回归,手机端多人联机,呼朋引伴一起重温当年的热血大作.除了IP,剧情,对工程师而言,<魂斗罗:归来>更要解决的联机同步和命中同步等问题,简单说,一颗子弹打没打中,没你 ...

  4. set 有序吗js_JavaScript Set没你想的那么简单!

    原标题:JavaScript Set没你想的那么简单! 来源 | blog.greenroots.info 译者 | 鬼哥 在本文中,我们将学习Set,并且使用几个小例子来彻底掌握Set,进来的小伙伴 ...

  5. 大公司为什么都有API网关?没你想的那么简单!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:rrd.me/g6eyJ 在这篇文章中将我们一起来探讨当前的 ...

  6. 分页缓冲池如何关闭_线程池没你想的那么简单

    前言 原以为线程池还挺简单的(平时常用,也分析过原理),这次是想自己动手写一个线程池来更加深入的了解它:但在动手写的过程中落地到细节时发现并没想的那么容易.结合源码对比后确实不得不佩服 Doug Le ...

  7. 天赋 VS 勤奋,“一万小时定律” 没你想得那么简单

    (文/马尔科姆·格拉德威尔)40年前,赫伯特· 西蒙(Herbert Simon)和威廉·蔡斯(William Chase) 在美国科学家杂志上刊登了一篇论文,在研究专业知识方面得出一个著名结论: & ...

  8. 【Python】Python中的for循环,没你想的那么简单~

    公众号:尤而小屋 作者:Peter 编辑:Peter 一年四季,循环往复:说到底就是一个循环的问题 for语句实际上解决的是循环问题.在很多的高级语言中都有for循环(for loop). for语句 ...

  9. 怎么把字符串变成数组_Java中字符串split() 的使用方法,没你想的那么简单

    先看下面的方法,事先预测一下,经过split方法,按逗号进行分割为数组之后,生成的数组的长度是多少,目测很多人都觉得是8,但是结果却出乎意料.是5而不是8. private static void t ...

最新文章

  1. Linux下查看显示器输出状态以及修改显示器工作模式(复制 or 扩展)
  2. JQuery:JQuery 中的CSS()方法
  3. 无人机数车--Drone-based Object Counting by Spatially Regularized Regional Proposal Network
  4. opensuse13.2 安裝五笔
  5. 计算机学院大学生程序设计竞赛(2015’11)1007 油菜花王国
  6. Qt学习笔记之常用控件QTreeWidget
  7. 站覆盖范围_武汉高铁站落地灯箱广告有什么投放价值?
  8. 阿里云终端连接与实例管理
  9. 自动语音识别的原理是什么,它的作用是什么
  10. cdq分治 陌上花开(内无题解)
  11. 程序员入门必备经典书单
  12. c++语言坦克大战源代码,C++代码之坦克大战(1)(示例代码)
  13. 「面试必背」Linux面试题(2022最新版)
  14. 使用xshell连接阿里云服务器【最近版、无坑系列】
  15. 利用U盘引导进入pe系统修复操作系统
  16. python用Selenium爬取携程网机票信息
  17. python中reduce是什么意思_Python----reduce原来是这样用的
  18. [置顶]CHENEY-YANG'S BLOG(cheney-yang)
  19. 2022-03-13-Redis
  20. 苹果系统中英文输入法切换_Mac系统,如何优雅切换中英文?

热门文章

  1. LeetCode 312. 戳气球(Burst Balloons)
  2. Spring Boot入门系列(十六)整合pagehelper,一秒实现分页功能!
  3. Python 中的json字符串以及使用
  4. adfs服务器获取信息失败,在ADFS服务器上SAML LogOutRequest处理失败
  5. C语言里面双分号是啥意思,问什么C程序里总是提示缺少分号;,而明明有分号?...
  6. java 双声道音频_Android 播放音频如何实现双声道效果
  7. python面试题_01
  8. Codeforces | CF1029F 【Multicolored Markers】
  9. 图的深度优先搜索(DFS)和广度优先搜索(BFS)算法
  10. Struts2中的图片验证码