Java线程的中断(Interruption)
任务和线程的启动很容易。在大多数时候,我们都会让它们运行直到结束,或者让它们自行停止。然而,有时候我们希望提前结束任务或线程,或许是因为用户取消了操作,或者应用程序需要被快速关闭。 要使任务和线程能安仝、快速、可靠地停止下来,并不是一件容易的事。Java的Thread类为我们提供了stop(),suspend()等停止挂起线程的方法,但是由于安全问题目前都已被弃用。Java并没有提供一种安全的抢占式方法来停止线程,但它提供了中断(Interruption),这是一种协作机制,采用协作式的方式使一个线程终止另一个线程的当前工作。 这种协作式的方法是必要的,我们很少希望某个任务、线程或服务立即停止,因为这种立即停止会使共享的数据结构处于不一致的状态。相反,在编写任务和服务时可以使用一种协作的方式:当需要停止时,它们首先会清除当前正在执行的工作,然后再结束。这提供了更好的灵活性,因为任务本身的代码比发出取消请求的代码更清楚如何执行清除工作。 生命周期结束(End-of-Lifecycle)的问题会使任务、服务以及程序的设计和实现等过程变得复杂,而这个在程序设计中非常重要的要素却经常被忽略。一个在行为良好的软件与勉强运行的软件之间的最主要区别就是,行为良好的软件能很完善地处理失败、关闭和取消等过程。
如何设计一种协作机制,让线程可以安全的中断呢?我们可以设置一个取消标志,在工作线程会被中断的地方去检查这个标志,当检查到这个中断标志被设置为已取消时,工作线程便开始做取消工作。
public class CancelableThread implements Runnable {
//线程取消标志,volatile修饰,保证内存可见性
private volatile boolean isCanceled = false;
@Override
public void run() {
while (!isCanceled) {//在工作线程中轮询检测这个取消标志
System.out.println("The current thread is doing something...");
System.out.println(Thread.currentThread().getName() + " cancel flag is " + isCanceled);
}
//当取消标志被设置为true,执行以下代码,可以做一些取消工作
System.out.println(Thread.currentThread().getName() + "The current thread Has been cancelled");
}
private void cancel() {
isCanceled = true;
}
}
public class Main {
public static void main(String[] args) throws Exception {
CancelableThread cancelableThread = new CancelableThread();
new Thread(cancelableThread).start();
try {
Thread.sleep(1);
} finally {
//设置标志位为true,中断线程
cancelableThread.cancel();
}
}
}
打印结果:
Thread-0 cancel flag is false
The current thread is doing something...
Thread-0 cancel flag is false
The current thread is doing something...
Thread-0 cancel flag is false
The current thread is doing something...
Thread-0 cancel flag is false
The current thread is doing something...
Thread-0 cancel flag is true
Thread-0The current thread Has been cancelled
其实Thread类为我们提供了三个与线程中断相关的方法,来实现上述机制。这三个方法分别是:
public void interrupt() {
//... 省略相关代码
interrupt0(); // Just to set the interrupt flag
//... 省略相关代码
}
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
public boolean isInterrupted() {
return isInterrupted(false);
}
- interrupt()方法主要用来设置中断标志位;如果此线程在调用Object类的wait(),wait(long)或wait(long,int)方法或join(),join(long),join(long,int) ,sleep(long)或sleep(long,int)的方法阻塞时,那么它的中断状态将被清除,并且会收到一个InterruptedException异常。
- 静态的interrupted()方法用来测试当前线程是否被中断,调用此方法会清除线程的中断状态。如果线程已被中断,调用此方法返回false;
- isInterrupted()方法用来测试当前线程是否被中断,但是不会清除线程的中断状态。
查看源码发现,静态的interrupted()和isInterrupted()方法都是调用的 private native boolean isInterrupted(boolean ClearInterrupted); 根据传入的ClearInterrupted的值,来判断是否要清除中断标志位。
public class InterruptTest {
static class InnerThread extends Thread{
@Override
public void run() {
while(!isInterrupted()){
System.out.println(Thread.currentThread().getName()+" cancle flag is "+isInterrupted());
try {
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
//抛出InterruptedException,中断标志位被清除,再次调用 interrupt();
interrupt();
}
}
System.out.println(Thread.currentThread().getName()+" cancle flag is "+isInterrupted());
}
}
public static void main(String[] args) {
InnerThread innerThread = new InnerThread();
innerThread.start();
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
innerThread.interrupt();
// InnerThread innerThread2 = new InnerThread();
// innerThread2.start();
// innerThread2.interrupt();
}
}
打印结果:
Thread-0 cancle flag is false
Thread-0 cancle flag is false
Thread-0 cancle flag is false
Thread-0 cancle flag is false
Thread-0 cancle flag is false
Thread-0 cancle flag is false
Thread-0 cancle flag is false
Thread-0 cancle flag is false
Thread-0 cancle flag is false
Thread-0 cancle flag is false
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at InterruptTest$InnerThread.run(InterruptTest.java:13)
Thread-0 cancle flag is true
参考资料:《Java并发编程实战》
Java线程的中断(Interruption)的更多相关文章
- Java线程的中断
引言 Java没有提供任何机制来安全地终止线程,但提供了中断机制,即thread.interrupt()方法.线程中断是一种协作式的机制,并不是说调用了中断方法之后目标线程一定会立即中断,而是发送了一 ...
- 理解java线程的中断(interrupt)
一个线程在未正常结束之前, 被强制终止是很危险的事情. 因为它可能带来完全预料不到的严重后果比如会带着自己所持有的锁而永远的休眠,迟迟不归还锁等. 所以你看到Thread.suspend, Threa ...
- java 线程的中断
Example12_6.java public class Example12_6 { public static void main(String args[]) { ClassRoom room6 ...
- Java线程机制学习
前面的文章中总结过Java中用来解决共享资源竞争导致线程不安全的几种常用方式: synchronized: ReentrantLock: ThreadLocal: 这些都是在简单介绍了基本用法的基础上 ...
- Java线程状态、线程start方法源码、多线程、Java线程池、如何停止一个线程
下面将依次介绍: 1. 线程状态.Java线程状态和线程池状态 2. start方法源码 3. 什么是线程池? 4. 线程池的工作原理和使用线程池的好处 5. ThreadPoolExecutor中的 ...
- java并发:中断一个正在运行的线程
要使任务和线程能安全可靠地停止,并不是一件很容易的事情,java没有提供任何机制来安全地终止线程,那么我们该怎么办呢? 下面我们先来了解一下java中的中断机制: java中断机制是一种协作机制,也就 ...
- java线程中断和终止线程运行
ava中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线程 ...
- lesson6:java线程中断
正常的情况下,业务系统都不会去中断它的线程,但是由于一些特殊情况的发生,线程已经不能正常结束了,并且此类线程已经影响到业务系统提供服务的能力,如果系统设计的健壮,便会通过监控线程去主动的中断此类线程. ...
- Java线程中断的本质深入理解(转)
一.Java中断的现象 首先,看看Thread类里的几个方法: public static boolean interrupted 测试当前线程是否已经中断.线程的中断状态 由该方法清除.换句话说,如 ...
随机推荐
- windows下程序启动检查,只启动一个实例
问题来源:http://bbs.csdn.net/topics/390998279?page=1#post-398983061 // Only_once.cpp : 定义控制台应用程序的入口点. // ...
- MTK Android software Tools工具的说明
MTK发布的Android software Tools工具包,里面包含了很多的MTK工具,如下是简要说明及学习文档 MTK Android software Tools工具的说明如下: 工具 说明 ...
- cocoa编程第4版 8.6 挑战2 解答
该版本的RaiseMan不用Array Controller,全部手写代码. 要注意的有以下几点: 1.TableView每列的sort设置和AC版的相同,但要手写排序代理方法 2.TableView ...
- 解决os x下gdb不能调试的问题
在较新的os x中使用gdb调试程序会发生 Unable to find Mach task port 之类的错误,这是由于新的os x内核禁止未授权的程序随意控制其他进程,如果不用root权限的话, ...
- 面试之路(10)-BAT面试之java实现单链表的插入和删除
链表的结构: 链表在空间是不连续的,包括: 数据域(用于存储数据) 指针域(用于存储下一个node的指针) 单项链表的代码实现: 节点类 构造函数 数据域的get,set方法 指针域的get,set方 ...
- “万能数据库查询分析器” 5.03发布,访问EXCEL将自动为表名前后加上中括弧
"万能数据库查询分析器" 5.03发布,访问EXCEL将自动为表名前后加上中括弧 1 引言 中国本土程序员马根峰推出的个人作品----万能数据库查询 ...
- 基于hashchange导航管理
想在五一放假的时候写出来,由于放假有点兴奋,心早就跑了,不废话了. 说一下基于hashchange导航管理: 浏览器的历史记录导航是用户非常常用的功能,除了点击前进后退按钮外,Window上的hist ...
- Oracle12c(12.1)中性能优化&功能增强之通过参数THREADED_EXECTION使用多线程模型
1. 后台 UNIX/Linux系统上,oracle用多进程模型.例如:linux上一个常规安装的数据库会有如下进程列: $ ps -ef | grep [o]ra_ oracle 15356 ...
- React Native入门 开发第一个React Native应用
1. 首先创建一个目录(比如ReactNativeDir),用于存放各个ReactNative工程的代码 2.使用React Native命令工具来创建(初始化)一个ReactNative项目(tes ...
- SpringBoot的第一个例子
1. 安装springboot的开发IDE,IntelliJ IDEA 2016.3.1这个工具,在IDE的官网上可以下载最新版本.https://www.jetbrains.com/idea/#ch ...