近期学习Java多线程的中断机制,网上的帖子说得很浅,并没深究其原理。看了Java源码,对Java的中断机制有了略深入的理解,在这篇文章中向感兴趣的网友分享下。这篇文章主要通过一个典型例子对中断机制进行剖析。

  一:一些概念和重要方法

  interrupt status(中断状态):请记住这个术语,中断机制就是围绕着这个字段来工作的。在Java源码中代表中断状态的字段是:private volatile Interruptible blocker;对“Interruptible”这个类不需要深入分析,对于“blocker”变量有以下几个操作。

  1.默认blocker=null; ®1

  2.调用方法“interrupt0();”将会导致“该线程的中断状态将被设置(JDK文档中术语)”。®2

  3.再次调用“interrupt0();”将会导致“其中断状态将被清除(同JDK文档中术语)”®3

  注:这三点很重要,接下来文章中会用来®1®2®3代替。

明白了第一点来看下文档中对于中断线程相关方法的描述。

  1.public void interrupt();

    中断线程。如果线程在调用 Object 类的 wait()wait(long)wait(long, int) 方法,或者该类的 join()join(long)join(long, int)sleep(long)sleep(long, int) 方法

  过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException。 

  2.public static boolean interrupted();

    测试当前线程是否已经中断。线程的中断状态 由该方法清除。线程中断被忽略,因为在中断时不处于活动状态的线程将由此返回 false 的方法反映出来。

      返回:
    如果当前线程已经中断,则返回 true;否则返回 false
      另请参见:
isInterrupted()

  3.public boolean isInterrupted();

    测试线程是否已经中断。线程的中断状态 不受该方法的影响。线程中断被忽略,因为在中断时不处于活动状态的线程将由此返回 false 的方法反映出来。

  返回:如果该线程已经中断,则返回 true;否则返回 false

  另请参见:interrupted()

  <!--来自JDK API文档-->

    以上三段中关于线程的中断状态 由该方法清除的描述,在源码层面就是®3调用。

 接下来说一下"interrupted()"和"isInterrupted()"两个方法的相同点和不同点。在这之前看一下源码中两个方法的代码,如下:

 public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
public boolean isInterrupted() {
return isInterrupted(false);
}
/**
* 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);

  相同点都是判断线程的interrupt status是否被设置,若被设置返回true,否则返回false.区别有两点:一:前者是static方法,调用者是current thread,而后者是普通方法,调用者是this current.二:它们其实都调用了Java中的一个native方法isInterrupted(boolean ClearInterrupted); 不同的是前者传入了参数true,后者传入了false.意义就是:前者将清除线程的interrupt state(®3),调用后者线程的interrupt state不受影响。

二:例子。

  接下来看一个例子,这个例子说明了两个问题。1.调用interrupt()方法并不会中断一个正在运行的线程.2.若调用sleep()而使线程处于阻塞状态,这时调用interrupt()方法,会抛出InterruptedException,从而使线程提前结束阻塞状态,退出阻塞代码。如下:

 package interrupt;

 public class Main {
/**
* @param args
*/
public static void main(String[] args) {
Main main = new Main();
Thread t = new Thread(main.runnable);
System.out.println("mainmainmain");
t.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t.interrupt();
} Runnable runnable = new Runnable() {
@Override
public void run() {
int i = 0;
try {
while (i < 1000) {
Thread.sleep(500);
System.out.println(i++);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}

运行结果:

 mainmainmain
0
1
2
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at interrupt.Main$1.run(Main.java:27)
at java.lang.Thread.run(Thread.java:619)

三:分析下例子中的中断机制

 1.为什么调用interrupt()并不能中断线程?

 public void interrupt() {
if (this != Thread.currentThread())
checkAccess(); synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt();
return;
}
}
interrupt0();
}

如上是Java源码中的代码,由此我们看出问题的答案。线程的blocker字段(也就是interrupt status)默认是null(®1)。调用interrupt()方法时,只是运行了®2,并没有进入if语句,所以没调用真正执行中断的代码b.interrupt().

2.若调用sleep()而使线程处于阻塞状态,这时调用interrupt()方法,会抛出InterruptedException,从而使线程提前结束阻塞状态,退出阻塞代码。为什么?

由上图可看出例子中30行代码铺好的异常其实是interrupt()抛出的,而不是sleep()抛出的。

欢迎交流!

Author:Andy Zhai

2014-01-12  17:54:39

Java多线程之interrupt()的深度研究的更多相关文章

  1. JAVA多线程之wait/notify

    本文主要学习JAVA多线程中的 wait()方法 与 notify()/notifyAll()方法的用法. ①wait() 与 notify/notifyAll 方法必须在同步代码块中使用 ②wait ...

  2. java多线程之yield,join,wait,sleep的区别

    Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...

  3. Java多线程之ConcurrentSkipListMap深入分析(转)

    Java多线程之ConcurrentSkipListMap深入分析   一.前言 concurrentHashMap与ConcurrentSkipListMap性能测试 在4线程1.6万数据的条件下, ...

  4. JAVA多线程之volatile 与 synchronized 的比较

    一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...

  5. Java多线程之Runnable与Thread

    Java多线程之Thread与Runnable 一.Thread VS Runnable 在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类和 ...

  6. JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止

    JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止 背景 当单线程的程序发生一个未捕获的异常时我们可以采用try....catch进行异常的捕获,但是在多线程环境 ...

  7. java多线程之wait和notify协作,生产者和消费者

    这篇直接贴代码了 package cn.javaBase.study_thread1; class Source { public static int num = 0; //假设这是馒头的数量 } ...

  8. java基础---->多线程之interrupt(九)

    这里我们通过实例来学习一下java多线程中关于interrupt方法的一些知识.执者失之.我想当一个诗人的时候,我就失去了诗,我想当一个人的时候,我就失去了我自己.在你什么也不想要的时候,一切如期而来 ...

  9. Java——多线程之Lock锁

    Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...

随机推荐

  1. (转)[置顶] Android APK反编译就这么简单 详解(附图) .

    在学习Android开发的过程你,你往往会去借鉴别人的应用是怎么开发的,那些漂亮的动画和精致的布局可能会让你爱不释手,作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用 ...

  2. JavaOOP-继承

    继承 1.继承的概念 继承是类与类之间的关系,是一个很简单很直观的概念,与现实世界中的继承(例如儿子继承父亲财产)类似. 继承可以理解为一个类从另一个类获取方法和属性的过程.如果类B继承于类A,那么B ...

  3. 如何用Word编辑参考文献------这是引用一位大师的

    如何用Word编辑参考文献修改文献是一件非常痛苦的事情,虽然现在也有很多软件可以编排参考文献,其实word本身就可以. 采用合适的编辑方法会方便地做到整齐,规范,自动排序和交叉引用.1.以尾注的方式插 ...

  4. Java基础学习笔记十一 Eclipse开发工具

    Eclipse是功能强大Java集成开发工具.它可以极大地提升我们的开发效率.可以自动编译,检查错误.在公司中,使用的就是Eclipse进行开发. Eclipse的下载.安装.卸载 下载 http:/ ...

  5. c语言第一次作业——输入与输出格式

    一.PTA实验作业 1.温度转换 本题要求编写程序,计算华氏温度150°F对应的摄氏温度.计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型. 1.实验代码 ...

  6. C语言第五次作业函数

    一.PTA实验作业 题目1: 6-6 使用函数输出水仙花数 1.本题PTA提交列表 2.设计思路 1.narcissistic函数 1.由于number的值后面会变化,所以定义d,e用于储存numbe ...

  7. Beta阶段敏捷冲刺报告-DAY1

    Beta阶段敏捷冲刺报告-DAY1 Scrum Meeting 敏捷开发日期 2017.11.2 讨论时间 20:30 讨论地点 下课路上以及院楼侧门 参会人员 项目组全体成员 会议内容 附加功能讨论 ...

  8. 2017-2018-1 1623 bug终结者 冲刺005

    bug终结者 冲刺005 by 20162323 周楠 今日任务:理清游戏运行逻辑,GameView类为游戏核心代码 简要介绍 游戏中整个地图都是由数组组成 1.整个地图为16×16格,主要元素有墙. ...

  9. vue.js下载及安装配置

    环境 Deepin15.4 下载及配置 node下载地址:http://nodejs.cn/download/ 解压到文件夹 /home/maskerk/vue/ 下 设置软连接: $ ln -s / ...

  10. Flask 应用最佳实践

    一个好的应用目录结构可以方便代码的管理和维护,一个好的应用管理维护方式也可以强化程序的可扩展性 应用目录结构 假定我们的应用主目录是"flask-demo",首先我们建议每个应用都 ...