为了账号安全,请及时绑定邮箱和手机立即绑定

Java线程的中断(Interruption)

Java线程的中断(Interruption)

永恒之光---原文地址

  任务和线程的启动很容易。在大多数时候,我们都会让它们运行直到结束,或者让它们自行停止。然而,有时候我们希望提前结束任务或线程,或许是因为用户取消了操作,或者应用程序需要被快速关闭。 要使任务和线程能安仝、快速、可靠地停止下来,并不是一件容易的事。Java的Thread类为我们提供了stop(),suspend()等停止挂起线程的方法,但是由于安全问题目前都已被弃用。Java并没有提供一种安全的抢占式方法来停止线程,但它提供了中断(Interruption),这是一种协作机制,采用协作式的方式使一个线程终止另一个线程的当前工作。 这种协作式的方法是必要的,我们很少希望某个任务、线程或服务立即停止,因为这种立即停止会使共享的数据结构处于不一致的状态。相反,在编写任务和服务时可以使用一种协作的方式:当需要停止时,它们首先会清除当前正在执行的工作,然后再结束。这提供了更好的灵活性,因为任务本身的代码比发出取消请求的代码更清楚如何执行清除工作。 生命周期结束(End-of-Lifecycle)的问题会使任务、服务以及程序的设计和实现等过程变得复杂,而这个在程序设计中非常重要的要素却经常被忽略。一个在行为良好的软件与勉强运行的软件之间的最主要区别就是,行为良好的软件能很完善地处理失败、关闭和取消等过程。

  如何设计一种协作机制,让线程可以安全的中断呢?我们可以设置一个取消标志,在工作线程会被中断的地方去检查这个标志,当检查到这个中断标志被设置为已取消时,工作线程便开始做取消工作。

复制代码

 1 public class CancelableThread implements Runnable { 2  3     //线程取消标志,volatile修饰,保证内存可见性 4     private volatile boolean isCanceled = false; 5  6     @Override 7     public void run() { 8         while (!isCanceled) {//在工作线程中轮询检测这个取消标志 9             System.out.println("The current thread is doing something...");10             System.out.println(Thread.currentThread().getName() + " cancel flag is " + isCanceled);11         }12         //当取消标志被设置为true,执行以下代码,可以做一些取消工作13         System.out.println(Thread.currentThread().getName() + "The current thread Has been cancelled");14     }15 16     private void cancel() {17         isCanceled = true;18     }19 }

复制代码

 

复制代码

 1 public class Main { 2     public static void main(String[] args) throws Exception { 3  4         CancelableThread cancelableThread = new CancelableThread(); 5         new Thread(cancelableThread).start(); 6         try { 7             Thread.sleep(1); 8         } finally { 9             //设置标志位为true,中断线程  10       cancelableThread.cancel();11         }12     }13 }

复制代码

打印结果:

12345678910Thread-0 cancel flag is falseThe current thread is doing something...Thread-0 cancel flag is falseThe current thread is doing something...Thread-0 cancel flag is falseThe current thread is doing something...Thread-0 cancel flag is falseThe current thread is doing something...Thread-0 cancel flag is trueThread-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的值,来判断是否要清除中断标志位。

复制代码

 1 public class InterruptTest { 2  3  4     static class InnerThread extends Thread{ 5  6  7         @Override 8         public void run() { 9             while(!isInterrupted()){10                 System.out.println(Thread.currentThread().getName()+" cancle flag is "+isInterrupted());11                 try {12 13                     Thread.sleep(100);14 15                 }catch (InterruptedException e){16                     e.printStackTrace();17                     //抛出InterruptedException,中断标志位被清除,再次调用 interrupt();18                     interrupt();19                 }20             }21             System.out.println(Thread.currentThread().getName()+" cancle flag is "+isInterrupted());22 23         }24     }25 26 27     public static void main(String[] args) {28         InnerThread innerThread = new InnerThread();29         innerThread.start();30         try {31 32             Thread.sleep(1000);33 34         }catch (InterruptedException e){35             e.printStackTrace();36         }37         innerThread.interrupt();38 //        InnerThread innerThread2 = new InnerThread();39 //        innerThread2.start();40 //        innerThread2.interrupt();41     }42 }

复制代码

打印结果:

复制代码

Thread-0 cancle flag is falseThread-0 cancle flag is falseThread-0 cancle flag is falseThread-0 cancle flag is falseThread-0 cancle flag is falseThread-0 cancle flag is falseThread-0 cancle flag is falseThread-0 cancle flag is falseThread-0 cancle flag is falseThread-0 cancle flag is falsejava.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并发编程实战》


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消