在瞭解InterruptedException異常以前應該瞭解如下的幾個關於線程的一些基礎知識。html
線程在必定的條件下會發生狀態的改變,下面是線程的一些狀態java
而InterruptedException異常從字面意思上就是中斷異常,那麼什麼是中斷呢?學習中斷以前咱們先了解一下具體什麼是阻塞bash
線程阻塞一般是指一個線程在執行過程當中暫停,以等待某個條件的觸發。而什麼狀況纔會使得線程進入阻塞的狀態呢?學習
若是咱們有一個運行中的軟件,例如是殺毒軟件正在全盤查殺病毒,此時咱們不想讓他殺毒,這時候點擊取消,那麼就是正在中斷一個運行的線程。ui
每個線程都有一個boolean類型的標誌,此標誌意思是當前的請求是否請求中斷,默認爲false。當一個線程A調用了線程B的interrupt方法時,那麼線程B的是否請求的中斷標誌變爲true。而線程B能夠調用方法檢測到此標誌的變化。this
/**
* @program: Test
* @description:
* @author: hu_pf@suixingpay.com
* @create: 2018-07-31 15:43
**/
public class InterrupTest implements Runnable{
public void run(){
try {
while (true) {
Boolean a = Thread.currentThread().isInterrupted();
System.out.println("in run() - about to sleep for 20 seconds-------" + a);
Thread.sleep(20000);
System.out.println("in run() - woke up");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();//若是不加上這一句,那麼cd將會都是false,由於在捕捉到InterruptedException異常的時候就會自動的中斷標誌置爲了false
Boolean c=Thread.interrupted();
Boolean d=Thread.interrupted();
System.out.println("c="+c);
System.out.println("d="+d);
}
}
public static void main(String[] args) {
InterrupTest si = new InterrupTest();
Thread t = new Thread(si);
t.start();
//主線程休眠2秒,從而確保剛纔啓動的線程有機會執行一段時間
try {
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("in main() - interrupting other thread");
//中斷線程t
t.interrupt();
System.out.println("in main() - leaving");
}
}
複製代碼
打印的參數以下:spa
in run() - about to sleep for 20 seconds-------false
in main() - interrupting other thread
in main() - leaving
c=true
d=false
複製代碼
如今知道線程能夠檢測到自身的標誌位的變化,可是他只是一個標誌,若是線程自己不處理的話,那麼程序仍是會執行下去,就比如,老師在學校叮囑要好好學習,具體何時,如何好好學習仍是看自身。.net
所以interrupt() 方法並不能當即中斷線程,該方法僅僅告訴線程外部已經有中斷請求,至因而否中斷還取決於線程本身線程
簡單的瞭解了什麼是阻塞和中斷之後,咱們就該瞭解碰到InterruptedException異常該如何處理了。日誌
有時候阻塞的方法拋出InterruptedException異常並不合適,例如在Runnable中調用了可中斷的方法,由於你的程序是實現了Runnable接口,而後在重寫Runnable接口的run方法的時候,那麼子類拋出的異常要小於等於父類的異常。而在Runnable中run方法是沒有拋異常的。因此此時是不能拋出InterruptedException異常。若是此時你只是記錄日誌的話,那麼就是一個不負責任的作法,由於在捕獲InterruptedException異常的時候自動的將是否請求中斷標誌置爲了false。至少在捕獲了InterruptedException異常以後,若是你什麼也不想作,那麼就將標誌從新置爲true,以便棧中更高層的代碼能知道中斷,而且對中斷做出響應。
捕獲到InterruptedException異常後恢復中斷狀態
public class TaskRunner implements Runnable {
private BlockingQueue<Task> queue;
public TaskRunner(BlockingQueue<Task> queue) {
this.queue = queue;
}
public void run() {
try {
while (true) {
Task task = queue.take(10, TimeUnit.SECONDS);
task.execute();
}
}
catch (InterruptedException e) {
// Restore the interrupted status
Thread.currentThread().interrupt();
}
}
}
複製代碼