Java 并发:线程中断-interrupt
一直以为执行了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的更多相关文章
- Java并发——线程中断学习
1. 使用interrupt()中断线程 当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一个标志,表示它已经被中断,并立即返 ...
- java之线程中断——interrupt
如下图所示,interrupt()方法并没有成功的中断我们的线程. 为了便于理解,其实可以这样来类比(注意,只是类比,实际情况并不完全是这样):Thread类中有一个boolean的标志域用来表示线程 ...
- Java 并发 线程同步
Java 并发 线程同步 @author ixenos 同步 1.异步线程本身包含了执行时需要的数据和方法,不需要外部提供的资源和方法,在执行时也不关心与其并发执行的其他线程的状态和行为 2.然而,大 ...
- Java 并发 线程属性
Java 并发 线程属性 @author ixenos 线程优先级 1.每当线程调度器有机会选择新线程时,首先选择具有较高优先级的线程 2.默认情况下,一个线程继承它的父线程的优先级 当在一个运行的线 ...
- Java 并发 线程的优先级
Java 并发 线程的优先级 @author ixenos 低优先级线程的执行时刻 1.在任意时刻,当有多个线程处于可运行状态时,运行系统总是挑选一个优先级最高的线程执行,只有当线程停止.退出或者由于 ...
- Java 并发 线程的生命周期
Java 并发 线程的生命周期 @author ixenos 线程的生命周期 线程状态: a) New 新建 b) Runnable 可运行 c) Running 运行 (调用 ...
- 线程中断 interrupt 和 LockSupport
本文章将要介绍的内容有以下几点,读者朋友也可先自行思考一下相关问题: 线程中断 interrupt 方法怎么理解,意思就是线程中断了吗?那当前线程还能继续执行吗? 判断线程是否中断的方法有几个,它们之 ...
- 从JDK源码角度看java并发线程的中断
线程的定义给我们提供了并发执行多个任务的方式,大多数情况下我们会让每个任务都自行执行结束,这样能保证事务的一致性,但是有时我们希望在任务执行中取消任务,使线程停止.在java中要让线程安全.快速.可靠 ...
- java并发:中断一个正在运行的线程
要使任务和线程能安全可靠地停止,并不是一件很容易的事情,java没有提供任何机制来安全地终止线程,那么我们该怎么办呢? 下面我们先来了解一下java中的中断机制: java中断机制是一种协作机制,也就 ...
随机推荐
- 火狐浏览器下,td 直接使用position:relative;和background:;产生的边框消失问题
消失示例: td{ width:40px; height:28px; position:relative; background:#ccc; } 出现问题 问题原因: 我的理解是各个浏览器之间对于ba ...
- 晦涩难懂的shell命令
初学shell脚本,过程中发现许多不易于理解的脚本语言,网上各种查找学习之后,择优精简一番,做出以下总结,方便以后遗忘了回顾,也为像我一样的初学者提供方便——推荐给初学者的一本书:<Linux ...
- JavaScript DOM编程艺术 笔记(三)函数
函数function 是在你的代码里随时调用的语句 每个函数是个短小的脚本,arguments,传递的参数 function name(arguments){ statements; } functi ...
- Cause: org.jetbrains.plugins.gradle.tooling.util.ModuleComponentIdentifierIm Lorg/gradle/api/artifacts/ModuleIdentifier;
今天碰到一个问题, 正常的下载gradle到本地,然后到spring官网上通过他们提供的start.spring.io创建一个demo项目, 然后在idea中打开,并配置下载的gradle到idea中 ...
- .Net Core 使用NLog记录日志到文件和数据库
NLog 记录日志是微软官方推荐使用. 接下来,通过配置日志记录到文件和Sql Server数据库. 第一步:首先添加包NLog.Config (可通过微软添加包命令Install-Package 包 ...
- driver failed programming external connectivity on endpoint wordpress
docker run 镜像的时候报错: [root@docker ~]# docker run -itd --name wordpress -p 88:80 wordpress:v1b77482f80 ...
- 学习Linux最简单的方法
大多数初学者在刚刚接触Linux都会有非常陌生的感觉.往往会有一些疑惑和问题.而我们就沿着这些问题,从远及近,从宏观到微观来理解Linux的简洁和美丽. 问题1:Winows有注册表,为什么Linux ...
- (转)C# 正则表达式
最近写爬虫时需要用到正则表达式,有段时间没有使用正则表达式现在渐渐感觉有些淡忘,现在使用还需要去查询一些资料.为了避免以后这样的情况,在此记录下正则表达式的一些基本使用方法附带小的实例.让以后在使用时 ...
- java的SSH的baseDao,巧用泛型
BaseDao接口: import java.util.List; public interface BaseDao<T,PK> { public void add(T t); publi ...
- Js 中的false,零值,null,undefined和空字符串对象
转自 http://www.imkevinyang.com/2009/07/javascript-中的false零值nullundefined和空字符串对象.html 在Javascript中,我们 ...