java中的中斷Thread.interrupt()意味着什么?


問題:Java里一個線程調用了Thread.interrupt()到底意味着什么?

     還有就是Thread.interrupted()會清除interrupted status意味着什么呢?是線程恢復了嗎?這里實在搞不懂

 

概念

  要弄清阻塞與中斷的關系,首先得弄清楚什么叫做阻塞,什么叫做中斷。

  阻塞表示線程的一種狀態,在這種狀態下,線程是不占用CPU的(也就是說,不執行你寫的命令代碼的),更進一步來說,也就是你的代碼在執行過程中,在某個地方暫停了。

  而中斷最初的含義是,指計算機運行過程中,出現某些意外情況需主機干預時,機器能自動停止正在運行的程序並轉入處理新情況的程序,處理完畢后又返回原被暫停的程序繼續運行。但在java中,中斷的作用明顯被弱化了,中斷更多的是指線程標志位的某個狀態,而中斷的處理邏輯需要用戶自己來進行定制(你可以選擇處理中斷,也可以選擇不處理),責任交給了用戶。

 

作者:Intopass
鏈接:https://www.zhihu.com/question/41048032/answer/89431513
來源:知乎

首先,一個線程不應該由其他線程來強制中斷或停止,而是應該由線程自己自行停止。
所以,Thread.stop, Thread.suspend, Thread.resume 都已經被廢棄了。
而 Thread.interrupt 的作用其實也不是中斷線程,而是「通知線程應該中斷了」,
具體到底中斷還是繼續運行,應該由被通知的線程自己處理。

具體來說,當對一個線程,調用 interrupt() 時,
  ① 如果線程處於被阻塞狀態(例如處於sleep, wait, join 等狀態),那么線程將立即退出被阻塞狀態,並拋出一個InterruptedException異常。僅此而已。
  ② 如果線程處於正常活動狀態,那么會將該線程的中斷標志設置為 true,僅此而已。被設置中斷標志的線程將繼續正常運行,不受影響。

interrupt() 並不能真正的中斷線程,需要被調用的線程自己進行配合才行。
也就是說,一個線程如果有被中斷的需求,那么就可以這樣做。
  ① 在正常運行任務時,經常檢查本線程的中斷標志位,如果被設置了中斷標志就自行停止線程。
  ② 在調用阻塞方法時正確處理InterruptedException異常。(例如,catch異常后就結束線程。)
Thread thread = new Thread(() -> {
    while (!Thread.interrupted()) {
        // do more work.
    }
});
thread.start();

// 一段時間以后
thread.interrupt();

具體到你的問題,Thread.interrupted()清除標志位是為了下次繼續檢測標志位。

如果一個線程被設置中斷標志后,選擇結束線程那么自然不存在下次的問題,
而如果一個線程被設置中斷標識后,進行了一些處理后選擇繼續進行任務,
而且這個任務也是需要被中斷的,那么當然需要清除標志位了。

 

 


作者:大閑人柴毛毛
鏈接:https://www.zhihu.com/question/41048032/answer/252905837
來源:知乎

interrupted()是Java提供的一種中斷機制,要把中斷搞清楚,還是得先系統性了解下什么是中斷機制。

什么是中斷?

在Java中沒有辦法立即停止一條線程,然而停止線程卻顯得尤為重要,如取消一個耗時操作。因此,Java提供了一種用於停止線程的機制——中斷。

  • 中斷只是一種協作機制,Java沒有給中斷增加任何語法,中斷的過程完全需要程序員自己實現。若要中斷一個線程,你需要手動調用該線程的interrupted方法,該方法也僅僅是將線程對象的中斷標識設成true;接着你需要自己寫代碼不斷地檢測當前線程的標識位;如果為true,表示別的線程要求這條線程中斷,此時究竟該做什么需要你自己寫代碼實現。
  • 每個線程對象中都有一個標識,用於表示線程是否被中斷;該標識位為true表示中斷,為false表示未中斷;
  • 通過調用線程對象的interrupt方法將該線程的標識位設為true;可以在別的線程中調用,也可以在自己的線程中調用。

中斷的相關方法

  • public void interrupt()
    將調用者線程的中斷狀態設為true。
  • public boolean isInterrupted()
    判斷調用者線程的中斷狀態。
  • public static boolean interrupted
    只能通過Thread.interrupted()調用。
    它會做兩步操作:
  1. 返回當前線程的中斷狀態;
  2. 將當前線程的中斷狀態設為false;

如何使用中斷?

  要使用中斷,首先需要在可能會發生中斷的線程中不斷監聽中斷狀態,一旦發生中斷,就執行相應的中斷處理代碼。
  當需要中斷線程時,調用該線程對象的interrupt函數即可。

1.設置中斷監聽

  正常的任務代碼被封裝在while循環中,每次執行完一遍任務代碼就檢查一下中斷狀態;一旦發生中斷,則跳過while循環,直接執行后面的中斷處理代碼。

2.觸發中斷

t1.interrupt();

  上述代碼執行后會將t1對象的中斷狀態設為true,此時t1線程的正常任務代碼執行完成后,進入下一次while循環前Thread.currentThread.isInterrupted()的結果為true,此時退出循環,執行循環后面的中斷處理代碼。

如何安全地停止線程?

  stop函數停止線程過於暴力,它會立即停止線程,不給任何資源釋放的余地,下面介紹兩種安全停止線程的方法。

1.循環標記變量

自定義一個共享的boolean類型變量,表示當前線程是否需要中斷。

  • 中斷標識
volatile boolean interrupted = false;
  • 任務執行函數
  Thread t1 = new Thread( new Runnable(){
public void run(){
        while(!interrupted){
            // 正常任務代碼……
        }
        // 中斷處理代碼……
        // 可以在這里進行資源的釋放等操作……
    }
} );
  • 中斷函數

 Thread t2 = new Thread( new Runnable(){

public void run(){
        interrupted = true;
    }
} );

2.循環中斷狀態

  • 中斷標識 
    由線程對象提供,無需自己定義。
  • 任務執行函數
  Thread t1 = new Thread( new Runnable(){
public void run(){
        while(!Thread.currentThread.isInterrupted()){
            // 正常任務代碼……
        }
        // 中斷處理代碼……
        // 可以在這里進行資源的釋放等操作……
    }
} );

  • 中斷函數
t1.interrupt();

  上述兩種方法本質一樣,都是通過循環查看一個共享標記為來判斷線程是否需要中斷,他們的區別在於:第一種方法的標識位是我們自己設定的,而第二種方法的標識位是Java提供的。除此之外,他們的實現方法是一樣的。

  上述兩種方法之所以較為安全,是因為一條線程發出終止信號后,接收線程並不會立即停止,而是將本次循環的任務執行完,再跳出循環停止線程。此外,程序員又可以在跳出循環后添加額外的代碼進行收尾工作。

如何處理中斷?

上文都在介紹如何獲取中斷狀態,那么當我們捕獲到中斷狀態后,究竟如何處理呢?

  • Java類庫中提供的一些可能會發生阻塞的方法都會拋InterruptedException異常,如:BlockingQueue#put、BlockingQueue#take、Object#wait、Thread#sleep。
  • 當你在某一條線程中調用這些方法時,這個方法可能會被阻塞很長時間,你可以在別的線程中調用當前線程對象的interrupt方法觸發這些函數拋出InterruptedException異常。
  • 當一個函數拋出InterruptedException異常時,表示這個方法阻塞的時間太久了,別人不想等它執行結束了。
  • 當你的捕獲到一個InterruptedException異常后,亦可以處理它,或者向上拋出。
  • 拋出時要注意???:當你捕獲到InterruptedException異常后,當前線程的中斷狀態已經被修改為false(表示線程未被中斷);此時你若能夠處理中斷,則不用理會該值;但如果你繼續向上拋InterruptedException異常,你需要再次調用interrupt方法,將當前線程的中斷狀態設為true。
  • 注意:絕對不能“吞掉中斷”!即捕獲了InterruptedException而不作任何處理。這樣違背了中斷機制的規則,別人想讓你線程中斷,然而你自己不處理,也不將中斷請求告訴調用者,調用者一直以為沒有中斷請求。

 


免責聲明!

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



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