一直以为执行了interrupt方法就可以让线程结束,并抛出InterruptedException. 今天看了Java并发编程实战的第七章发现并不是这么回事,在这章的开头就提到

要使任务和线程能安全、快速、可靠地停止下来,并不是一件容易的事。Java没有提供任何机制来安全地终止线程。但它提供了(Interruption),这是一种协作机制,能够使一个线程终止另一个线程的当前工作

如上提到的是协作,而不是强制。因为如果需要被中断的线程任务实现没有准守这样的协作约定,那么其他线程就没有办法通过interrupt去中断它。比如下面的foreverThread就没有对interrupt设置的boolean变量进行检测。

        Thread foreverThread = new Thread(new Runnable() {
@Override
public void run() {
int t = ;
for (int i = ; i < ; i++) {
i--;
if (t++ % == ) {
System.out.println(".");
}
}
}
});
foreverThread.start();
foreverThread.interrupt();

如书中所述,每个线程都有一个boolean类型的中断状态,我们可以通过调用线程的interrupt方法来设置这个值为true,并通过isInterrupted方法来检测这个值是否被置为true。这样当一个线程(比如主线程)通过调用另外一个(比如任务)线程interrupt方法,然后这个任务线程内有检测该boolean值是否置位的逻辑,如果为true这中止当前的工作,然后按照库方法那样抛出一个InterruptException来提示当前任务执行被中断了。因为interrupt设置这个boolean变量是线程体相关的,一次设置后它会一直存在于线程体,这样如果不把它重新置为false,那么执行后续其他会检测这个变量的操作就会立即退出抛出InterruptException。出于这样的原因,当检测到这个boolean标记被设为true后,在要抛出InterruptException之前,还要通过调用Thread.interrupted()方法来重置这个boolean标记(即设为false)以免影响后续的操作(这也表示执行这个动作的这部分代码处理了这次中断请求,至于怎么处理,一般就是上文所说的抛出InterruptException)。

阻塞库方法,例如Thread.sleep和Object.wait等,都会检测线程何时中断,并且在发现中断时提前返回。它们在响应中断时执行的操作包括:清除中断状态,抛出InterruptException,表示阻塞操作由于中断而提前结束。

线程实例的interrupt方法用于设置boolean标记,静态的Thread.interrupted方法用于清除boolean标记(即置为false,同时返回以前的boolean值)下面是一个实例:

        Thread iThread = Thread.currentThread();

        iThread.interrupt();

        System.out.println(iThread.isInterrupted());

        System.out.println(Thread.interrupted());

        System.out.println(iThread.isInterrupted());

输出如下:

true
true
false

使用静态的interrupted时应该小心,因为它会清除当前线程的中断状态。如果在调用interrupted时返回了true,那么除非你想屏蔽这个中断,否则必须对它进行处理——可以抛出InterruptedException,或者通过再次调用interrupt来恢复中断

如果我们在检测到interrupt中断后,抛出异常却不调用interrupted清除标记,那么会影响到以后的其他可中断调用:

        BlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>();

        Thread iThread = Thread.currentThread();

        iThread.interrupt();

        System.out.println(iThread.isInterrupted());

        try {
queue.take();
} catch (InterruptedException e) {
System.out.println("thread is interrupted, isInterrupted:" + iThread.isInterrupted());
}

输出:

true
thread is interrupted, isInterrupted:false

运行以上代码片段,程序会立即结束而不会再queue.take()上等待。在库函数抛出InterruptException后,通过isInterrupted检测可以发现中断boolean标记已经被清除(置为false)

Java 并发:线程中断-interrupt的更多相关文章

  1. Java并发——线程中断学习

    1. 使用interrupt()中断线程 当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一个标志,表示它已经被中断,并立即返 ...

  2. java之线程中断——interrupt

    如下图所示,interrupt()方法并没有成功的中断我们的线程. 为了便于理解,其实可以这样来类比(注意,只是类比,实际情况并不完全是这样):Thread类中有一个boolean的标志域用来表示线程 ...

  3. Java 并发 线程同步

    Java 并发 线程同步 @author ixenos 同步 1.异步线程本身包含了执行时需要的数据和方法,不需要外部提供的资源和方法,在执行时也不关心与其并发执行的其他线程的状态和行为 2.然而,大 ...

  4. Java 并发 线程属性

    Java 并发 线程属性 @author ixenos 线程优先级 1.每当线程调度器有机会选择新线程时,首先选择具有较高优先级的线程 2.默认情况下,一个线程继承它的父线程的优先级 当在一个运行的线 ...

  5. Java 并发 线程的优先级

    Java 并发 线程的优先级 @author ixenos 低优先级线程的执行时刻 1.在任意时刻,当有多个线程处于可运行状态时,运行系统总是挑选一个优先级最高的线程执行,只有当线程停止.退出或者由于 ...

  6. Java 并发 线程的生命周期

    Java 并发 线程的生命周期 @author ixenos 线程的生命周期 线程状态: a)     New 新建 b)     Runnable 可运行 c)     Running 运行 (调用 ...

  7. 线程中断 interrupt 和 LockSupport

    本文章将要介绍的内容有以下几点,读者朋友也可先自行思考一下相关问题: 线程中断 interrupt 方法怎么理解,意思就是线程中断了吗?那当前线程还能继续执行吗? 判断线程是否中断的方法有几个,它们之 ...

  8. 从JDK源码角度看java并发线程的中断

    线程的定义给我们提供了并发执行多个任务的方式,大多数情况下我们会让每个任务都自行执行结束,这样能保证事务的一致性,但是有时我们希望在任务执行中取消任务,使线程停止.在java中要让线程安全.快速.可靠 ...

  9. java并发:中断一个正在运行的线程

    要使任务和线程能安全可靠地停止,并不是一件很容易的事情,java没有提供任何机制来安全地终止线程,那么我们该怎么办呢? 下面我们先来了解一下java中的中断机制: java中断机制是一种协作机制,也就 ...

随机推荐

  1. Security-OAuth2.0 密码模式之服务端实现

    第一步:配置数据库 ,固定创建三张表 ,OAuth2 框架需要默认使用这三张表 我使用的时Mysql,工具为navcat CREATE TABLE `oauth_access_token` ( `to ...

  2. Myeclipse设置自动联想功能

    ///声明,博客园暂无转载功能,这篇博客是转载自贞心真义. 最近初学Java,正在使用MyEclipse来编写新的项目,刚开始打开MyEclipse感觉这个工具既陌生又熟悉,熟悉之处在于编辑器的几大共 ...

  3. [原创]php任务调度器 hellogerard/jobby

    目录 简介 安装 标准使用 选项 项目实践 简介 一个强大的php层面上的定时任务调度器, 无需修改系统层面的crontab 实际中, php 结合 crontab 来实现定时任务是一种经得住考验的实 ...

  4. postman小结

    1.get和post请求,get有限制2k,post没有限制post安全 在选择的时候别把get post选错然后,run 2.data 选成txt文件  utf-8 ip ip,result12.1 ...

  5. Github概念理解备忘录

    总结: add就是用来建立跟踪,添加文件到缓存区: commit就是把文件缓存区的文件正式加到本地库中: push就是把本地库更新到远程库中: git命令的操作要在仓库所在目录下进行才有效: 在Git ...

  6. 除法保留小数bit位 + 四舍五入

    /*num1/num2 保留bit 位小数 , 四舍五入*/ #include<bits/stdc++.h> using namespace std; ]; int main() { in ...

  7. 【实战】Axis2后台Getshell

    实战遇到的情况---任意文件读取,读取/conf/axis2.xml内容,读取用户名和密码登录后台 当然弱口令也是屡试不爽的. 操作起来 1.上传cat.aar(链接:https://pan.baid ...

  8. Visual Studio 跨平台開發實戰(4) - Xamarin Android 基本控制項介紹 (转帖)

    前言 不同於iOS, Xamarin 在Visual Studio中針對Android, 可以直接設計使用者介面. 在本篇教學文章中, 筆者會針對Android的專案目錄結構以及基本控制項進行介紹, ...

  9. Vagrant 创建虚拟机

    Vagrant  创建虚拟机 1. 下载相关软件 虚拟机软件:vmware  virtualbox Vagrant 软件:vagrant cd /tmpwget http://download.vir ...

  10. 003javascript语句

    javascript语句和java差不多,注意==和===区别 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" " ...