任务和线程的启动很容易。在大多数时候,我们都会让它们运行直到结束,或者让它们自行停止。然而,有时候我们希望提前结束任务或线程,或许是因为用户取消了操作,或者应用程序需要被快速关闭。 要使任务和线程能安仝、快速、可靠地停止下来,并不是一件容易的事。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);
}
  1. interrupt()方法主要用来设置中断标志位;如果此线程在调用Object类的wait(),wait(long)或wait(long,int)方法或join(),join(long),join(long,int) ,sleep(long)或sleep(long,int)的方法阻塞时,那么它的中断状态将被清除,并且会收到一个InterruptedException异常。
  2. 静态的interrupted()方法用来测试当前线程是否被中断,调用此方法会清除线程的中断状态。如果线程已被中断,调用此方法返回false;
  3. 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)的更多相关文章

  1. Java线程的中断

    引言 Java没有提供任何机制来安全地终止线程,但提供了中断机制,即thread.interrupt()方法.线程中断是一种协作式的机制,并不是说调用了中断方法之后目标线程一定会立即中断,而是发送了一 ...

  2. 理解java线程的中断(interrupt)

    一个线程在未正常结束之前, 被强制终止是很危险的事情. 因为它可能带来完全预料不到的严重后果比如会带着自己所持有的锁而永远的休眠,迟迟不归还锁等. 所以你看到Thread.suspend, Threa ...

  3. java 线程的中断

    Example12_6.java public class Example12_6 { public static void main(String args[]) { ClassRoom room6 ...

  4. Java线程机制学习

    前面的文章中总结过Java中用来解决共享资源竞争导致线程不安全的几种常用方式: synchronized: ReentrantLock: ThreadLocal: 这些都是在简单介绍了基本用法的基础上 ...

  5. Java线程状态、线程start方法源码、多线程、Java线程池、如何停止一个线程

    下面将依次介绍: 1. 线程状态.Java线程状态和线程池状态 2. start方法源码 3. 什么是线程池? 4. 线程池的工作原理和使用线程池的好处 5. ThreadPoolExecutor中的 ...

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

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

  7. java线程中断和终止线程运行

    ava中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线程 ...

  8. lesson6:java线程中断

    正常的情况下,业务系统都不会去中断它的线程,但是由于一些特殊情况的发生,线程已经不能正常结束了,并且此类线程已经影响到业务系统提供服务的能力,如果系统设计的健壮,便会通过监控线程去主动的中断此类线程. ...

  9. Java线程中断的本质深入理解(转)

    一.Java中断的现象 首先,看看Thread类里的几个方法: public static boolean interrupted 测试当前线程是否已经中断.线程的中断状态 由该方法清除.换句话说,如 ...

随机推荐

  1. Cocos2D的随机数生成函数

    有很多种方法生成随机数.但是只有arc4random函数生成的最接近于"真随机(truly random)"数.(而且不需要种子) 其变体函数arc4random_uniform生 ...

  2. Hibernate统计表中的条数

     /** * 判断积分日志表中是否有某个用户的注册日志 */@Transactional(propagation = Propagation.REQUIRED)public boolean isE ...

  3. 套接字编程相关函数(2:TCP套接字编程相关函数)

    本文摘录自<UNIX网络编程 卷1>. 基本套接字函数 socket函数 为了执行网络I/O,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型.其定义如下: #in ...

  4. Linux - gcc 的简易用法 (编译、参数与链结)

    # 仅将原始码编译成为目标档,并不制作连结等功能: [root@www ~]# gcc -c hello.c # 会自动的产生 hello.o 这个文件,但是并不会产生 binary 运行档. # 在 ...

  5. 【51】java设计模式-工厂设计模式剖析

    工厂设计设计模式的分类: 工厂模式在<Java与模式>中分为三类: 1)简单工厂模式(Simple Factory):不利于产生系列产品: 2)工厂方法模式(Factory Method) ...

  6. UITableView设置单元格选中后只显示一个打勾的三种简单方法(仅供参考)

    1.第一种方法:先定位到最后一行,若选中最后一行直接退出,否则用递归改变上次选中的状态,重新设置本次选中的状态. - (UITableViewCell*)tableView:(UITableView* ...

  7. 使用vs2010 opencv2.4.4编译release版本程序

    大体上要注意一下几点内容: 1.vc++目录的选择上,库目录选择为opencv目录中的staticlib目录 2.在链接->输入->附加依赖库,中添加,相应的staticlib库目录中的所 ...

  8. mac os X中关于dayone缓存的实际文件位置

    最近刚安装了mac版的dayone软件,感觉蛮不错的!以前一直用iphone版的,mac版是要米的,68米丫!想了想还是一咬牙:买了! 我用的是iCloud同步,虽然资料放在云中,但本地还是会有缓存的 ...

  9. azkaban报错记录

    问题信息:Failed to build job executor for job o2o_get_file_ftp1Job type 'command ' is unrecognized. Coul ...

  10. 第15章-输入/输出 --- File类

    (一) Java的IO通过java.io包下的类和接口来支持,在java.io包下主要包括输入.输出两种IO流. 每种输入.输出流又分为字节流和字符流两大类: (1)字节流以字节为单位来处理输入.输出 ...