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()中斷

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM