我們在coding的時候,會經常遇到要求我們處理InterruptedException的情況,本文將解釋如何正確處理此異常以及背後的原因。 ...
何時會出現InterruptedException?
當一個線程處於阻塞狀態下(例如休眠)的情況下,調用了該線程的interrupt()方法,則會出現InterruptedException。
@Test public void testName() throws Exception { // 被中斷的線程 final Thread t = new Thread(){ @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { // 當調用t.interrupt(),則會刨除此異常 e.printStackTrace(); } } }; // 去中斷t的線程 new Thread(new Runnable() { public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } t.interrupt(); } }).start(); t.start(); t.join(); }View Code
先說結論:
public void interrupt()方法意為向該線程發起中斷請求,所以當出現此異常的情況下,如果該線程在此時應該被中斷,不要吞掉此異常信息,則應該在catch塊里完成任務的情況工作,如果該線程不應該在此時被中斷,則應該調用Thread.currentThread().interrupt() 方法設置中斷標示,讓後續的代碼來檢查並處理異常,通過Thread.interrupted()方法,可以檢查中斷標記。
概括如下: 1.不要生吞此異常; 2.如果可以處理此異常:完成清理工作之後退出; 3.不處理此異常,不繼續執行任務:重新拋出; 4.不處理此異常,繼續執行任務:捕捉到異常之後恢復中斷標記(交由後續程式檢查中斷)。 下麵對上述提到的Thread.currentThread().interrupt() 和 Thread.interrupted() 二個方法進行解釋:(長相相似,註意區分)public void interrupt() 方法解釋:
作用:
代替廢棄的stop()方法[暴力停止線程],不直接中止線程,而是傳遞給目標線程一個“應該關閉”的信號,由目標線程自行處理。“應該關閉”的信號的具體體現:
當目標線程處於阻塞狀態,會拋出InterruptedException,而不會將標示位設置為true。 當目標線程處於非阻塞狀態,會將標示位設置為true,不會拋出異常。應用場景:
取消“可取消的任務” 舉例:當用戶發起一項請求,後端的代碼正在進行(可能此任務的代碼運行時間比較長),這個時候用戶想取消這個請求,如果直接調用stop()方法,則此線程會“戛然而止”,我們都知道,web的請求絕大情況下都會有對於資料庫的操作,然後此時線程退出,則事務沒有提交,這就會造成數據不一致的情況;或者該線程正在持有redis中的鎖,那麼這樣的話,就會造成鎖不能及時的釋放,所以要使用interrupted()方法,但是這還不夠,我們需要在代碼中適當的位置檢查中斷請求,使用Thread.interrupted()靜態方法,然後返回true,則進行相應的取消處理。static boolean interrupted() 方法解釋:
作用:測試當前線程是否已被中斷:返回中斷標示位,並且重置中斷標示位為false。