在瞭解InterruptedException異常以前應該瞭解如下的幾個關於線程的一些基礎知識。html
線程在必定的條件下會發生狀態的改變,下面是線程的一些狀態java
<center><img src="http://p9jfgo4wc.bkt.clouddn.com/thread.png"/></center>學習
而InterruptedException異常從字面意思上就是中斷異常,那麼什麼是中斷呢?學習中斷以前咱們先了解一下具體什麼是阻塞ui
線程阻塞一般是指一個線程在執行過程當中暫停,以等待某個條件的觸發。而什麼狀況纔會使得線程進入阻塞的狀態呢?this
若是咱們有一個運行中的軟件,例如是殺毒軟件正在全盤查殺病毒,此時咱們不想讓他殺毒,這時候點擊取消,那麼就是正在中斷一個運行的線程。.net
每個線程都有一個boolean類型的標誌,此標誌意思是當前的請求是否請求中斷,默認爲false。當一個線程A調用了線程B的interrupt方法時,那麼線程B的是否請求的中斷標誌變爲true。而線程B能夠調用方法檢測到此標誌的變化。線程
/** * @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"); } }
打印的參數以下:日誌
in run() - about to sleep for 20 seconds-------false in main() - interrupting other thread in main() - leaving c=true d=false
如今知道線程能夠檢測到自身的標誌位的變化,可是他只是一個標誌,若是線程自己不處理的話,那麼程序仍是會執行下去,就比如,老師在學校叮囑要好好學習,具體何時,如何好好學習仍是看自身。code
所以interrupt() 方法並不能當即中斷線程,該方法僅僅告訴線程外部已經有中斷請求,至因而否中斷還取決於線程本身htm
簡單的瞭解了什麼是阻塞和中斷之後,咱們就該瞭解碰到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(); } } }