java---interrupt、interrupted和isInterrupted的區別

1、interrupt() 
interrupt方法用於中斷線程。調用該方法的線程的狀態爲將被置爲"中斷"狀態。
注意:線程中斷僅僅是置線程的中斷狀態位,不會停止線程。需要用戶自己去監視線程的狀態爲並做處理。支持線程中斷的方法(也就是線程中斷後會拋出interruptedException的方法)就是在監視線程的中斷狀態,一旦線程的中斷狀態被置爲“中斷狀態”,就會拋出中斷異常。

 

2、interrupted() 和 isInterrupted()

首先看一下API中該方法的實現:
1 public static boolean interrupted () {
2      return currentThread().isInterrupted(true);
3 }
該方法就是直接調用當前線程的isInterrupted(true)的方法。
然後再來看一下API中 isInterrupted的實現:
1 public boolean isInterrupted () {
2      return isInterrupted( false);
3 }

該方法卻直接調用當前線程的isInterrupted(false)的方法。

因此這兩個方法有兩個主要區別:
  1. interrupted 是作用於當前線程,isInterrupted 是作用於調用該方法的線程對象所對應的線程。(線程對象對應的線程不一定是當前運行的線程。例如我們可以在A線程中去調用B線程對象的isInterrupted方法。)
  2. 這兩個方法最終都會調用同一個方法-----isInterrupted( Boolean 參數),,只不過參數固定爲一個是true,一個是false;               注意: isInterrupted( Boolean 參數)是isInterrupted( )的重載方法。
 
由於第二個區別主要體現在調用的方法的參數上,讓我們來看一看這個參數是什麼含義
 
先來看一看被調用的方法 isInterrupted(boolean arg)(Thread類中重載的方法)的定義:
1 private native boolean isInterrupted( boolean ClearInterrupted);
原來這是一個本地方法,看不到源碼。不過沒關係,通過參數名ClearInterrupted我們就能知道,這個參數代表是否要清除狀態位。

如果這個參數爲true,說明返回線程的狀態位後,要清掉原來的狀態位(恢復成原來情況)。這個參數爲false,就是直接返回線程的狀態位。

這兩個方法很好區分,只有當前線程才能清除自己的中斷位(對應interrupted()方法)

 

於是寫了個例子想驗證一下:

 

  1. public class Interrupt {  
  2.     public static void main(String[] args) throws Exception {  
  3.         Thread t = new Thread(new Worker());  
  4.         t.start();  
  5.           
  6.         Thread.sleep(200);  
  7.         t.interrupt();  
  8.           
  9.         System.out.println("Main thread stopped.");  
  10.     }  
  11.       
  12.     public static class Worker implements Runnable {  
  13.         public void run() {  
  14.             System.out.println("Worker started.");  
  15.               
  16.             try {  
  17.                 Thread.sleep(500);  
  18.             } catch (InterruptedException e) {  
  19.                 System.out.println("Worker IsInterrupted: " +   
  20.                         Thread.currentThread().isInterrupted());  
  21.             }  
  22.               
  23.             System.out.println("Worker stopped.");  
  24.         }  
  25.     }  
  26. }  

內容很簡答:主線程main啓動了一個子線程Worker,然後讓worker睡500ms,而main睡200ms,之後main調用worker線程的interrupt方法去中斷worker,worker被中斷後打印中斷的狀態。下面是執行結果:

 

 

  1. Worker started.  
  2. Main thread stopped.  
  3. Worker IsInterrupted: false  
  4. Worker stopped.  

Worker明明已經被中斷,而isInterrupted()方法竟然返回了false,爲什麼呢?

在stackoverflow上搜索了一圈之後,發現有網友提到:可以查看拋出InterruptedException方法的JavaDoc(或源代碼),於是我查看了Thread.sleep方法的文檔,doc中是這樣描述這個InterruptedException異常的:

 

  1. InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.  



 

結論:interrupt方法是用於中斷線程的,調用該方法的線程的狀態將被置爲"中斷"狀態。注意:線程中斷僅僅是設置線程的中斷狀態位,不會停止線程。所以當一個線程處於中斷狀態時,如果再由wait、sleep以及jion三個方法引起的阻塞,那麼JVM會將線程的中斷標誌重新設置爲false,並拋出一個InterruptedException異常,然後開發人員可以中斷狀態位“的本質作用-----就是程序員根據try-catch功能塊捕捉jvm拋出的InterruptedException異常來做各種處理,比如如何退出線程。總之interrupt的作用就是需要用戶自己去監視線程的狀態位並做處理。

 

同時可以做這樣的理解:
Thread.currentThread().interrupt(); 這個用於清除中斷狀態,這樣下次調用Thread.interrupted()方法時就會一直返回爲true,因爲中斷標誌已經被恢復了。
而調用isInterrupted()只是簡單的查詢中斷狀態,不會對狀態進行修改。

interrupt()是用來設置中斷狀態的。返回true說明中斷狀態被設置了而不是被清除了。我們調用sleep、wait等此類可中斷(throw InterruptedException)方法時,一旦方法拋出InterruptedException,當前調用該方法的線程的中斷狀態就會被jvm自動清除了,就是說我們調用該線程的isInterrupted 方法時是返回false。如果你想保持中斷狀態,可以再次調用interrupt方法設置中斷狀態。這樣做的原因是,java的中斷並不是真正的中斷線程,而只設置標誌位(中斷位)來通知用戶。如果你捕獲到中斷異常,說明當前線程已經被中斷,不需要繼續保持中斷位。
interrupted是靜態方法,返回的是當前線程的中斷狀態。例如,如果當前線程被中斷(沒有拋出中斷異常,否則中斷狀態就會被清除),你調用interrupted方法,第一次會返回true。然後,當前線程的中斷狀態被方法內部清除了。第二次調用時就會返回false。如果你剛開始一直調用isInterrupted,則會一直返回true,除非中間線程的中斷狀態被其他操作清除了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章