淺談Thread.sleep()為什麼要拋出中斷異常
從場景說起
假設sleep()方法不拋出中斷異常,也就是線程沒有中斷響應能力,會怎麼樣?
考慮如下場景:
線程A:sleep中
線程B:A別睡瞭,要關機啦(向A發送中斷信號)
線程A:sleep中
這樣好嗎?這不好。因為線程A對外界情況沒有感知能力。
中斷就起到瞭這樣的作用:讓線程具有感知的能力。sleep(),wait()等方法都需要你去處理中斷異常,也就是需要你的代碼能夠響應中斷。
響應中斷
什麼叫能夠響應中斷呢?下面這段最常見的代碼可以響應嗎?
try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }
答案是可以響應,但還不夠。為什麼呢?
如下圖,官方文檔說瞭:拋異常的同時,該線程的中斷狀態會被清除。
那中斷狀態清除瞭,有什麼影響嗎?
當然有,我們一般代碼都會這樣寫:(目的:休眠100毫秒後,判斷線程是否被中斷,如果未被中斷則繼續執行業務)
try { Thread.sleep(100); } catch (InterruptedException e) { //中斷標志已經被清除瞭 } // Thread.currentThread().isInterrupted():是否被中斷瞭(是否有中斷標志) if(!Thread.currentThread().isInterrupted()) { //如果沒有被中斷,則處理業務 doSomething(); }
如果你運行起來會發現,即使線程在sleep期間被中斷,我們下面的代碼依然會執行。為什麼呢?就是因為sleep是會擦除中斷標志的。
那你可能會說:我為什麼要寫if(!Thread.currentThread().isInterrupted())呢?我平時都不判斷的。
首先這是個demo,主要是展示效果。其次,我們任何代碼都要有響應中斷的能力,所以一般加個while(!Thread.currentThread().isInterrupted())。
回到上面的demo,如果要實現休眠100毫秒後,判斷線程是否被中斷,如果未被中斷則繼續執行業務該怎麼辦?
很簡單,我們在本線程再中斷一次即可。代碼如下:
try { Thread.sleep(100); } catch (InterruptedException e) { //中斷標志已經被清除瞭 // 手動中斷本線程,將本線程打上中斷信號。 Thread.currentThread().interrupt(); } // Thread.currentThread().isInterrupted():是否被中斷瞭(是否有中斷標志) if(!Thread.currentThread().isInterrupted()) { //如果沒有被中斷,則處理業務 doSomething(); }
如上述代碼所示,我們手動調用interrupt()方法即可。這樣業務代碼就不會執行瞭。
關閉線程池
可能上述理論你還是有些懵。下面進入實戰環節。
那麼我們看看線程池如何關閉?
有兩個API:
void shutdown():等待隊列和當前執行的任務會繼續執行完。
List<Runnable> shutdownNow():對所有正在執行的任務線程發送中斷信號。等待隊列的任務會被返回。
這下你知道為什麼我們代碼需要有響應中斷的能力瞭嗎?我們先舉一個無法停掉線程的例子:
ExecutorService executorService = Executors.newFixedThreadPool(1); executorService.execute(()->{ //任務一直跑 while (true) { System.out.println("1"); } }); Thread.sleep(10); executorService.shutdownNow();
你看,我們根本無法停掉任務,根本無法關閉線程池!
所以while(!Thread.currentThread().isInterrupted())才對嘛。
怎麼關呢?代碼我就不寫瞭,關鍵點如下:
1.你的代碼一定要有響應中斷的能力。
2.sleep等方法就有這個能力。但是他會擦除中斷標志位,記得調用Thread.currentThread().interrupt()恢復中斷標志位哦。
到此這篇關於淺談Thread.sleep()為什麼要拋出中斷異常的文章就介紹到這瞭,更多相關Thread.sleep()拋出中斷異常內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Java如何固定大小的線程池
- java高並發InterruptedException異常引發思考
- Java線程中斷interrupt的常用方法
- java中斷機制實例講解
- Java多線程Thread類的使用及註意事項