淺談Thread.sleep()為什么要拋出中斷異常
從場景說起
假設(shè)sleep()方法不拋出中斷異常,也就是線程沒有中斷響應(yīng)能力,會怎么樣?
考慮如下場景:
線程A:sleep中
線程B:A別睡了,要關(guān)機(jī)啦(向A發(fā)送中斷信號)
線程A:sleep中
這樣好嗎?這不好。因為線程A對外界情況沒有感知能力。
中斷就起到了這樣的作用:讓線程具有感知的能力。sleep(),wait()等方法都需要你去處理中斷異常,也就是需要你的代碼能夠響應(yīng)中斷。
響應(yīng)中斷
什么叫能夠響應(yīng)中斷呢?下面這段最常見的代碼可以響應(yīng)嗎?
try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }
答案是可以響應(yīng),但還不夠。為什么呢?
如下圖,官方文檔說了:拋異常的同時,該線程的中斷狀態(tài)會被清除。
那中斷狀態(tài)清除了,有什么影響嗎?
當(dāng)然有,我們一般代碼都會這樣寫:(目的:休眠100毫秒后,判斷線程是否被中斷,如果未被中斷則繼續(xù)執(zhí)行業(yè)務(wù))
try { Thread.sleep(100); } catch (InterruptedException e) { //中斷標(biāo)志已經(jīng)被清除了 } // Thread.currentThread().isInterrupted():是否被中斷了(是否有中斷標(biāo)志) if(!Thread.currentThread().isInterrupted()) { //如果沒有被中斷,則處理業(yè)務(wù) doSomething(); }
如果你運(yùn)行起來會發(fā)現(xiàn),即使線程在sleep期間被中斷,我們下面的代碼依然會執(zhí)行。為什么呢?就是因為sleep是會擦除中斷標(biāo)志的。
那你可能會說:我為什么要寫if(!Thread.currentThread().isInterrupted())呢?我平時都不判斷的。
首先這是個demo,主要是展示效果。其次,我們?nèi)魏未a都要有響應(yīng)中斷的能力,所以一般加個while(!Thread.currentThread().isInterrupted())。
回到上面的demo,如果要實現(xiàn)休眠100毫秒后,判斷線程是否被中斷,如果未被中斷則繼續(xù)執(zhí)行業(yè)務(wù)該怎么辦?
很簡單,我們在本線程再中斷一次即可。代碼如下:
try { Thread.sleep(100); } catch (InterruptedException e) { //中斷標(biāo)志已經(jīng)被清除了 // 手動中斷本線程,將本線程打上中斷信號。 Thread.currentThread().interrupt(); } // Thread.currentThread().isInterrupted():是否被中斷了(是否有中斷標(biāo)志) if(!Thread.currentThread().isInterrupted()) { //如果沒有被中斷,則處理業(yè)務(wù) doSomething(); }
如上述代碼所示,我們手動調(diào)用interrupt()方法即可。這樣業(yè)務(wù)代碼就不會執(zhí)行了。
關(guān)閉線程池
可能上述理論你還是有些懵。下面進(jìn)入實戰(zhàn)環(huán)節(jié)。
那么我們看看線程池如何關(guān)閉?
有兩個API:
void shutdown():等待隊列和當(dāng)前執(zhí)行的任務(wù)會繼續(xù)執(zhí)行完。
List<Runnable> shutdownNow():對所有正在執(zhí)行的任務(wù)線程發(fā)送中斷信號。等待隊列的任務(wù)會被返回。
這下你知道為什么我們代碼需要有響應(yīng)中斷的能力了嗎?我們先舉一個無法停掉線程的例子:
ExecutorService executorService = Executors.newFixedThreadPool(1); executorService.execute(()->{ //任務(wù)一直跑 while (true) { System.out.println("1"); } }); Thread.sleep(10); executorService.shutdownNow();
你看,我們根本無法停掉任務(wù),根本無法關(guān)閉線程池!
所以while(!Thread.currentThread().isInterrupted())才對嘛。
怎么關(guān)呢?代碼我就不寫了,關(guān)鍵點(diǎn)如下:
1.你的代碼一定要有響應(yīng)中斷的能力。
2.sleep等方法就有這個能力。但是他會擦除中斷標(biāo)志位,記得調(diào)用Thread.currentThread().interrupt()恢復(fù)中斷標(biāo)志位哦。
到此這篇關(guān)于淺談Thread.sleep()為什么要拋出中斷異常的文章就介紹到這了,更多相關(guān)Thread.sleep()拋出中斷異常內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot實現(xiàn)單點(diǎn)登錄的實現(xiàn)詳解
在現(xiàn)代的Web應(yīng)用程序中,單點(diǎn)登錄(Single?Sign-On)已經(jīng)變得越來越流行,在本文中,我們將使用Spring?Boot構(gòu)建一個基本的單點(diǎn)登錄系統(tǒng),需要的可以參考一下2023-05-05有關(guān)ServletConfig與ServletContext的訪問
下面小編就為大家?guī)硪黄嘘P(guān)ServletConfig與ServletContext的訪問。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01Spring MVC url提交參數(shù)和獲取參數(shù)
本文重要講述通過url提交參數(shù)和獲取參數(shù)的具體操作與實現(xiàn)。具有很好的參考價值。下面跟著小編一起來看下吧2017-04-04使用Vue+Spring Boot實現(xiàn)Excel上傳功能
這篇文章主要介紹了使用Vue+Spring Boot實現(xiàn)Excel上傳,需要的朋友可以參考下2018-11-11JAVA中JSONObject對象和Map對象之間的相互轉(zhuǎn)換
這篇文章主要介紹了JAVA中JSONObject對象和Map對象之間的相互轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01基于Properties實現(xiàn)配置數(shù)據(jù)庫驅(qū)動
這篇文章主要介紹了基于Properties實現(xiàn)配置數(shù)據(jù)庫驅(qū)動,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-05-05