1. 程式人生 > >java執行緒中的interrupt,isInterrupt,interrupted方法

java執行緒中的interrupt,isInterrupt,interrupted方法

在java的執行緒Thread類中有三個方法,比較容易混淆,在這裡解釋一下
(1)interrupt:置執行緒的中斷狀態
(2)isInterrupt:執行緒是否中斷
(3)interrupted:返回執行緒的上次的中斷狀態,並清除中斷狀態

舉個例子:
  1. 用法:  
  2. class MyThread extends Thread {  
  3.     ......  
  4.     ......  
  5.     publicvoid run() {  
  6.         try {  
  7.             while(!Thread.currentThread().isInterrupted()) {  
  8.                 //當達到佇列容量時,在這裡會阻塞
  9.                 //put的內部會呼叫LockSupport.park()這個是用來阻塞執行緒的方法
  10.                 //當其他執行緒,呼叫此執行緒的interrupt()方法時,會設定一箇中斷標誌
  11.                 //LockSupport.part()中檢測到這個中斷標誌,會丟擲InterruptedException,並清除執行緒的中斷標誌
  12.                 //因此在異常段呼叫Thread.currentThread().isInterrupted()返回為false
  13.                 ArrayBlockingQueue.put(somevalue);   
  14.             }  
  15.         } catch (InterruptedException e) {  
  16.             //由於阻塞庫函式,如:Object.wait,Thread.sleep除了丟擲異常外,還會清除執行緒中斷狀態,因此可能在這裡要保留執行緒的中斷狀態
  17.             Thread.currentThread().interrupt();  
  18.         }  
  19.     }  
  20.     publicvoid cancel() {  
  21.         interrupt();  
  22.     }  
  23. }  
  24. 外部呼叫  
  25. MyThread thread = new MyThread();  
  26. thread.start();  
  27. ......  
  28. thread.cancel();  
  29. thread.isInterrupted();  


一般來說,阻塞函式,如:Thread.sleep、Thread.join、Object.wait、LockSupport.park等在檢查到執行緒的中斷狀態時,會丟擲InterruptedException,同時會清除執行緒的中斷狀態

對於InterruptedException的處理,可以有兩種情況:
(1)外層程式碼可以處理這個異常,直接丟擲這個異常即可
(2)如果不能丟擲這個異常,比如在run()方法內,因為在得到這個異常的同時,執行緒的中斷狀態已經被清除了,需要保留執行緒的中斷狀態,則需要呼叫Thread.currentThread().interrupt()

另外,Thread.interrupted()在jdk庫的原始碼中比較常用,因為它既可以得到上一次執行緒的中斷標誌值,又可以同時清除執行緒的中斷標誌,一舉兩得,但同時也有壞處,就是這個函式有清除中斷狀態的副作用,不容易理解