java线程中断Interrupted用法

停止一个线程的主要机制是中断,中断并不代表强迫终止一个线程,

它是一种协作机制,是给线程传递一个取消的信号,

但是让线程来决定如何以及何时退出。

这句话可谓是线程中断的核心原理了;光看文字还是很模糊的,用代码说事吧。

 1 public class ThreadEnd implements Runnable {
 2 
 3     private volatile static boolean ok=false;
 4     @Override
 5     public void run() {
 6        for(;;){
 7             if(Thread.currentThread().isInterrupted()){
 8                 System.out.println("我进入了中断线程的条件中,将要结束run方法");
 9                 break;//因为是for死循环,用这种方式退出循环
10             }else{
11                 System.out.println("我没有收到中断信息");
12             }
13         }
14     }
15 
16 
17 
18     public static void main(String[] args) throws InterruptedException {
19         Thread thread = new Thread(new ThreadEnd());
20         thread.start();
21         Thread.sleep(1000);
22         thread.interrupt();
23         System.out.println("主线程结束");
24 
25     }
26 }

在第6行中不停的死循环来查看线程 isInterrupted()方法是否返回true;

第22行代码给线程调用了线程中断方法,第7行条件满足,最终退出线程。

那么有一个疑问:是不是所有的线程都可以用interrupt()方法进行中断呢?

比如说sleep的线程,比如说等待锁的线程?我们挨个来求解吧。

sleep休眠线程中断代码

 1 public class InterruptionSleepThread implements Runnable {
 2 
 3     @Override
 4     public void run() {
 5         try {
 6             System.out.println("本大爷要休眠50秒,你能奈我何?");
 7             Thread.sleep(50000);//休眠50秒
 8         } catch (InterruptedException e) {
 9             System.out.println("休眠的线程收到中断信号,利用抛异常的方式将本大爷从梦中叫醒,结束线程。");
10             e.printStackTrace();
11         }
12     }
13     public static void main(String[] args) throws InterruptedException {
14         Thread thread = new Thread(new InterruptionSleepThread());
15         thread.start();
16         Thread.sleep(2000);
17         thread.interrupt();
18         System.out.println("主线程结束");
19 
20     }
21 }

打印结果

从上面的打印结果来看,休眠的线程是的确退出来了,虽然这个叫醒的方式不怎么优雅(异常的方式)。

这也从另外一个角度告诉了我们,为什么每次在run()里面调用sleep()方法的时候,编译器要我们强制进行异常捕获了,也是为了程序安全。

等待锁的过程中,被中断的代码

 1 public class WaitLockThreadInterrupted extends Thread {
 2 
 3     private static Object lock =new Object();
 4 
 5     @Override
 6     public  void run() {
 7         System.out.println("我要等待test锁释放后,才能执行下面的代码");
 8         synchronized (lock){
 9           while (true){
10               if(Thread.currentThread().isInterrupted()){
11                   System.out.println("我收到线程中断的信号");
12                   break;
13               }else{
14                   System.out.println("没收到线程中断的信号");
15               }
16           }
17         }
18     }
19 
20     private static void test() throws InterruptedException {
21         synchronized (lock){
22             Thread thread=new Thread(new WaitLockThreadInterrupted());
23             thread.start();
24             Thread.sleep(1000);
25             thread.interrupt();
26             System.out.println("已发出中断信号");
27             thread.join();//阻塞test方法,一直到线程thread执行完毕。
28         }
29     }
30 
31     public static void main(String[] args) throws InterruptedException {
32       test();
33     }
34 }

打印结果

虽然打印了结果,但是左边的红灯一直亮着,并且也没有打印11行的内容,表示线程一直没有退出来。

分析代码:test中的synchronized()和run方法中的synchronized用了同一个对象锁,

所以22行的thread线程中的run方法的执行,必须等到test释放掉lock锁对象才行;

但是 test中用thread.join()方法来告诉我们,等thread线程执行完毕了,我才能放你们走。

完了,死锁了。

这种死锁的状态如果25行代码发出中断信号有用的话,这种死锁的尴尬是能够解开的。

从打印结果来看 interrupt()是不能中断等待锁的线程的。

结论:

1.Runnable状态(正在运行或者等待调度的线程)可以用interrupt()中断

2.Block状态(等待锁的线程)不可以用interrupt()中断

猜你喜欢

转载自www.cnblogs.com/guoyansi19900907/p/12585601.html
今日推荐