为什么80%的码农都做不了架构师?>>>   

今天在看到Thread类的isInterrupted方法可以获取线程的中断状态:

于是写了个例子想验证一下:

public class Interrupt {public static void main(String[] args) throws Exception {Thread t = new Thread(new Worker());t.start();Thread.sleep(200);t.interrupt();System.out.println("Main thread stopped.");}public static class Worker implements Runnable {public void run() {System.out.println("Worker started.");try {Thread.sleep(500);} catch (InterruptedException e) {System.out.println("Worker IsInterrupted: " + Thread.currentThread().isInterrupted());}System.out.println("Worker stopped.");}}
}

内容很简答:主线程main启动了一个子线程Worker,然后让worker睡500ms,而main睡200ms,之后main调用worker线程的interrupt方法去中断worker,worker被中断后打印中断的状态。下面是执行结果:

Worker started.
Main thread stopped.
Worker IsInterrupted: false
Worker stopped.

Worker明明已经被中断,而isInterrupted()方法竟然返回了false,为什么呢?

在stackoverflow上搜索了一圈之后,发现有网友提到:可以查看抛出InterruptedException方法的JavaDoc(或源代码),于是我查看了Thread.sleep方法的文档,doc中是这样描述这个InterruptedException异常的:

InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.

注意到后面这句“当抛出这个异常的时候,中断状态已被清除”。所以isInterrupted()方法应该返回false。可是有的时候,我们需要isInterrupted这个方法返回true,怎么办呢?这里就要先说说interrupt, interrupted和isInterrupted的区别了:

interrupt方法是用于中断线程的,调用该方法的线程的状态将被置为"中断"状态。注意:线程中断仅仅是设置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出InterruptedException的方法,比如这里的sleep,以及Object.wait等方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。这个观点可以通过这篇文章证实:

interrupt() merely sets the thread's interruption status. Code running in the interrupted thread can later poll the interrupted status to see if it has been requested to stop what it is doing

再来看看interrupted方法的实现:

public static boolean interrupted() {return currentThread().isInterrupted(true);
}

和isInterrupted的实现:

public boolean isInterrupted() {return isInterrupted(false);
}

这两个方法一个是static的,一个不是,但实际上都是在调用同一个方法,只是interrupted方法传入的参数为true,而iInterrupted传入的参数为false。那么这个参数到底是什么意思呢?来看下这个isInterrupted(boolean)方法的实现:

/*** Tests if some Thread has been interrupted.  The interrupted state* is reset or not based on the value of ClearInterrupted that is* passed.*/
private native boolean isInterrupted(boolean ClearInterrupted);

这是一个native方法,看不到源码没有关系,参数名字ClearInterrupted已经清楚的表达了该参数的作用----是否清除中断状态。方法的注释也清晰的表达了“中断状态将会根据传入的ClearInterrupted参数值确定是否重置”。所以,静态方法interrupted将会清除中断状态(传入的参数ClearInterrupted为true),而实例方法isInterrupted则不会(传入的参数ClearInterrupted为false)。

回到刚刚的问题:很明显,如果要isInterrupted这个方法返回true,通过在调用isInterrupted方法之前再次调用interrupt()方法来恢复这个中断的状态即可:

public class Interrupt  {public static void main(String[] args) throws Exception {Thread t = new Thread(new Worker());t.start();Thread.sleep(200);t.interrupt();System.out.println("Main thread stopped.");}public static class Worker implements Runnable {public void run() {System.out.println("Worker started.");try {Thread.sleep(500);} catch (InterruptedException e) {Thread curr = Thread.currentThread();//再次调用interrupt方法中断自己,将中断状态设置为“中断”curr.interrupt();System.out.println("Worker IsInterrupted: " + curr.isInterrupted());System.out.println("Worker IsInterrupted: " + curr.isInterrupted());System.out.println("Static Call: " + Thread.interrupted());//clear statusSystem.out.println("---------After Interrupt Status Cleared----------");System.out.println("Static Call: " + Thread.interrupted());System.out.println("Worker IsInterrupted: " + curr.isInterrupted());System.out.println("Worker IsInterrupted: " + curr.isInterrupted());}System.out.println("Worker stopped.");}}
}

执行结果:

Worker started.
Main thread stopped.
Worker IsInterrupted: true
Worker IsInterrupted: true
Static Call: true
---------After Interrupt Status Cleared----------
Static Call: false
Worker IsInterrupted: false
Worker IsInterrupted: false
Worker stopped.

从执行结果也可以看到,前两次调用isInterrupted方法都返回true,说明isInterrupted方法不会改变线程的中断状态,而接下来调用静态的interrupted()方法,第一次返回了true,表示线程被中断,第二次则返回了false,因为第一次调用的时候已经清除了中断状态。最后两次调用isInterrupted()方法就肯定返回false了。

那么,在什么场景下,我们需要在catch块里面中断线程(重置中断状态)呢?

答案是:如果不能抛出InterruptedException(就像这里的Thread.sleep语句放在了Runnable的run方法中,这个方法不允许抛出任何受检查的异常),但又想告诉上层调用者这里发生了中断的时候,就只能在catch里面重置中断状态了。

以下内容来自:Dealing with InterruptedException

If you catch InterruptedException but cannot rethrow it, you should preserve evidence that the interruption occurred so that code higher up on the call stack can learn of the interruption and respond to it if it wants to. This task is accomplished by calling interrupt() to "reinterrupt" the current thread, as shown in Listing 3.

Listing 3: Restoring the interrupted status after catching InterruptedException

public class TaskRunner implements Runnable {private BlockingQueue<Task> queue;public TaskRunner(BlockingQueue<Task> queue) { this.queue = queue; }public void run() { try {while (true) {Task task = queue.take(10, TimeUnit.SECONDS);task.execute();}} catch (InterruptedException e) { // Restore the interrupted statusThread.currentThread().interrupt();}}
}

那么问题来了:为什么要在抛出InterruptedException的时候清除掉中断状态呢?

这个问题没有找到官方的解释,估计只有Java设计者们才能回答了。但这里的解释似乎比较合理:一个中断应该只被处理一次(你catch了这个InterruptedException,说明你能处理这个异常,你不希望上层调用者看到这个中断)。

对于这个问题,如果有更好的解释,欢迎留言讨论。

参考地址:

http://stackoverflow.com/questions/7142665/why-does-thread-isinterrupted-always-return-false

http://stackoverflow.com/questions/2523721/why-do-interruptedexceptions-clear-a-threads-interrupted-status

http://www.ibm.com/developerworks/library/j-jtp05236/

http://blog.csdn.net/z69183787/article/details/25076033

转载于:https://my.oschina.net/itblog/blog/787024

对Java中interrupt、interrupted和isInterrupted的理解相关推荐

  1. java中interrupt,interrupted和isInterrupted的区别

    文章目录 isInterrupted interrupted interrupt java中interrupt,interrupted和isInterrupted的区别 前面的文章我们讲到了调用int ...

  2. Thread中interrupt()interrupted()和isInterrupted()的区别

    2019独角兽企业重金招聘Python工程师标准>>> 在java线程中,线程的状态分为6种.官方文档的解释是: /*** Thread state for a thread whi ...

  3. 关于java中位运算符的使用和理解

    关于java中位运算符的使用和理解 &(按位与) ' & ' 符号的作用是对运算符的两侧以二进制表达的操作符按位进行'与'运算. 规则: 只有两个操作数对应位同为1时,结果为1,其余全 ...

  4. 【JAVA多线程】interrupted() 和 isInterrupted() 的区别

    Thread 类中提供了两种方法用来判断线程的状态是不是停止的.就是我们今天的两位主人公 interrupted() 和 isInterrupted() . interrupted() 官方解释:测试 ...

  5. Java中关于进程和线程的理解

    进程:进程是操作系统的基础结构,是一次程序的执行,是一个程序及其数据在处理机上顺序执行所发生的的活动,是程序在数据集合上运行的过程,它是操作系统进行资源调度和分配的一个  独            立 ...

  6. java中的泛型的使用与理解

    什么是泛型? 泛型是程序设计语言的一种特性.允许程序员在强类型程序设计语言中编写 体验泛型 代码时定义一些可变部份,那些部份在使用前必须作出指明.各种程序设计语言和其编译器.运行环境对泛型的支持均不一 ...

  7. java中对象的生存期_深入理解Java虚拟机-判断对象是否存活算法与对象引用

    我们知道Java中的对象一般存放在堆中,但是总不能让这些对象一直占着内存空间,这些对象最终都会被回收并释放内存,那么我们如何判断对象已经成为垃圾呢?这篇文章会提出两种算法解决这个问题.另外,本文还要谈 ...

  8. java中==与equals的区别及理解_Java开发中常量池的理解与归纳

    相关概念 1.什么是常量 用final修饰的成员变量表示常量,值一旦给定就无法改变! final修饰的变量有三种:静态变量.实例变量和局部变量,分别表示三种类型的常量. 2.Class文件中的常量池 ...

  9. 【Java中断言(assert)的理解】

    目录 1. 简介 2. 使用 3. 语法 4. 应用实例 5. 断言的不足之处 6. 对assert的思考 1. 简介 Java语言中的断言功能在项目中一般很少使用,我在第一次断言的时候是在查看spr ...

最新文章

  1. python【蓝桥杯vip练习题库】BASIC-17矩阵乘法(枚举)
  2. 第一百三十期:14种常见编程语言的优缺点及应用范围
  3. 安装kenlm出现问题的解决方案gcc g++
  4. MySQL常见面试题与答案
  5. 面试 | 阿里P7级别程序猿亲身告知,不会面试,还想进大厂?做梦吧
  6. 【高并发】JUC中的Executor框架详解1
  7. MyEclipse安装插件的几种方法
  8. 【深入理解Java原理】ThreadLocal
  9. 全国大学生“高教杯“成图大赛:关于蜗轮蜗杆快速建模研究(一)
  10. 分享一款代码生成工具,可自定义模板生成不同的代码
  11. 蒋文华《博弈论》笔记及视频摘录
  12. Set和Map数据结构。
  13. java雷霆战机图片_JAVA开发《雷霆战机》雷电类游戏效果演示
  14. Educode--头歌 《软件工程》实验作业2
  15. 刘盈盈计算机科学与技术,四川省2013年度中等职业学校省级优秀毕业生名单_29131...
  16. windows 如何批量修改文件后缀名?
  17. 虚拟主机可以运行java_下面哪种类型的文件可以在Java虚拟机中运行( ).
  18. 生化危机绝密报告2java,生化危机2重制版,玩家一路尾随暴君,却发现暴君不见光的小秘密...
  19. linux终端装什么系统下载软件,在Ubuntu 18.04系统中下载安装Termite终端的方法
  20. 微信小程序之仿微信漂流瓶

热门文章

  1. 做软件测试适合女生吗?
  2. 不同物理机与虚拟机之间的通信
  3. range函数python范围_python的range函数与切片操作符
  4. matlab二维离散/阶梯/极坐标图形绘制
  5. 申宝证券-个股涨跌对半开
  6. SQL优化终于干掉了“distinct”
  7. 移动端h5页面与原生app的交互
  8. HTML 基础-11-表单-单选功能和默认选中
  9. java int在那个包_int nextInt()
  10. VScode创建maven项目(包含maven配置)