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 测试当前线程是否已经中断.线程的中断状态 由该方法清除.换句话说,如 ...
随机推荐
- Cocos2D绘制纹理的一般方法
如果你想在通常情况下绘制纹理,最简单的方法是在CCSprite的子类中实现.否则你将不得不自己创建一个CCRenderState对象传递给blend模式,着色器以及(可选的)纹理给CCRenderer ...
- EasyUI中tree,Datagrid,pagenation的使用EasyUI中Datagrid和pagenation进行关联时,再次点击pagenation时让表格数据显示的问题
// 获取选中一行的情况,下面的一个参数可以代表一个DataGridfunction getSelected(dialogEle,dataFileTextEle) { // 获取选中一行的情况. va ...
- 求二叉树深度和copy二叉树
// operatorTree.cpp // 对树的操作 #include <iostream> #include <cstdio> // 二叉树表示法 typedef str ...
- linux进程的介绍和管理
概述 - 在linux 中,每个执行的程序都称为一个进程,每一个进程都分配一个ID号 - 每一个进程,都会对应一个父进程,而这个父进程可以复制多个子进程,例如www服务器 - 每个进程都可 ...
- PS图层混合算法之四(亮光, 点光, 线性光, 实色混合)
亮光模式: 根据绘图色通过增加或降低"对比度",加深或减淡颜色.如果绘图色比50%的灰亮,图像通过降低对比度被照亮,如果绘图色比50%的灰暗,图像通过增加对比度变暗. 线性光模式: ...
- C# DataTable,DataSet,IList,IEnumerable 互转扩展属性
using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.R ...
- shell脚本调用python脚本的路径问题
脚本的相互调用中,只有在同一级目录下才可以使用__file__参数去获取路径名,(在shell里使用pwd也同样),否则,使用的就是主文件(最开始运行的脚本程序)的所在位置,是错误路径:一定要注意当期 ...
- Hadoop基本知识,(以及MR编程原理)
hadoop核心是:MapReduce和HDFS (对应着job执行(程序)和文件存储系统(数据的输入和输出)) CRC32作数据交验:在文件Block写入的时候除了写入数据还会写入交验信息,在读取 ...
- CUDA版本的OpenCL在windows 7的下编程初步
参考文献: http://blog.csdn.net/neoxmu/article/details/8866928 我安装的是CUDA5.5,代码如下: //#include "stdafx ...
- ruby中顶层定义的方法究竟放在哪里?
ruby中顶层(top level)中定义的方法放在main中,证明如下: self.private_methods(false) #IN TOP LEVEL 那么methods方法究竟是在哪定义的, ...