亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

關(guān)閉線程池我們可以選擇什么都不做,JVM 關(guān)閉時自然的會清除線程池對象。當(dāng)然這么做,存在很大的弊端,線程池中正在執(zhí)行執(zhí)行的線程以及隊列中還未執(zhí)行任務(wù)將會變得極不可控。所以我們需要想辦法控制到這些未執(zhí)行的任務(wù)以及正在執(zhí)行的線程。

線程池 API 提供兩個主動關(guān)閉的方

法 ThreadPoolExecutor#shutdownNow 與 ThreadPoolExecutor#shutdown,這兩個方法都可以用于關(guān)閉線程池,但是具體效果卻不太一樣。

一、線程池的狀態(tài)

在說線程池關(guān)閉方法之前,我們先了解線程池狀態(tài)。

線程池狀態(tài)關(guān)系圖如下:

你關(guān)閉線程池的方法安全嗎?

 

 

從上圖我們看到線程池總共存在 5 種狀態(tài),分別為:

  • RUNNING:線程池創(chuàng)建之后的初始狀態(tài),這種狀態(tài)下可以執(zhí)行任務(wù)。
  • SHUTDOWN:該狀態(tài)下線程池不再接受新任務(wù),但是會將工作隊列中的任務(wù)執(zhí)行結(jié)束。
  • STOP: 該狀態(tài)下線程池不再接受新任務(wù),但是不會處理工作隊列中的任務(wù),并且將會中斷線程。
  • TIDYING:該狀態(tài)下所有任務(wù)都已終止,將會執(zhí)行 terminated() 鉤子方法。
  • TERMINATED:執(zhí)行完 terminated() 鉤子方法之后。

當(dāng)我們執(zhí)行 ThreadPoolExecutor#shutdown 方法將會使線程池狀態(tài)從 RUNNING 轉(zhuǎn)變?yōu)?nbsp;SHUTDOWN。而調(diào)用 ThreadPoolExecutor#shutdownNow 之后線程池狀態(tài)將會從 RUNNING 轉(zhuǎn)變?yōu)?nbsp;STOP。從上面的圖上還可以看到,當(dāng)線程池處于 SHUTDOWN,我們還是可以繼續(xù)調(diào)用 ThreadPoolExecutor#shutdownNow 方法,將其狀態(tài)轉(zhuǎn)變?yōu)?nbsp;STOP 。

二、ThreadPoolExecutor#shutdown

上面我們知道線程池狀態(tài),這里先說說 shutdown 方法。shutdown 方法源碼比較簡單,能比較直觀理解其調(diào)用邏輯。

shutdown 方法源碼:

你關(guān)閉線程池的方法安全嗎?

 

 

shutdown 方法首先加鎖,其次先檢查系統(tǒng)安裝狀態(tài)。接著就會將線程池狀態(tài)變?yōu)?nbsp;SHUTDOWN,在這之后線程池不再接受提交的新任務(wù)。此時如果還繼續(xù)往線程池提交任務(wù),將會使用線程池拒絕策略響應(yīng),默認(rèn)情況下將會使用 ThreadPoolExecutor.AbortPolicy,拋出 RejectedExecutionException 異常。

interruptIdleWorkers 方法只會中斷空閑的線程,不會中斷正在執(zhí)行任務(wù)的的線程。空閑的線程將會阻塞在線程池的阻塞隊列上。

線程池構(gòu)造參數(shù)需要指定 coreSize(核心線程池數(shù)量),maximumPoolSize(最大的線程池數(shù)量),keepAliveTime(多余空閑線程等待時間),unit(時間單位),workQueue(阻塞隊列)。

當(dāng)調(diào)用線程池的 execute 方法,線程池工作流程如下:

  1. 如果此時線程池中線程數(shù)量小于 coreSize,將會新建線程執(zhí)行提交的任務(wù)。
  2. 如果此時線程池線程數(shù)量已經(jīng)大于 coreSize,將會直接把任務(wù)加入到隊列中。線程將會從工作隊列中獲取任務(wù)執(zhí)行。
  3. 如果工作隊列已滿,將會繼續(xù)新建線程。
  4. 如果工作隊列已滿,且線程數(shù)等于 maximumPoolSize,此時將會使用拒絕策略拒絕任務(wù)。
  5. 超過 coreSize 數(shù)量那部分線程,如果空閑了 keepAliveTime ,線程將會終止。

工作流程圖如下:

你關(guān)閉線程池的方法安全嗎?

 

 

當(dāng)線程池處于第二步時,線程將會使用 workQueue#take 獲取隊頭的任務(wù),然后完成任務(wù)。如果工作隊列一直沒任務(wù),由于隊列為阻塞隊列,workQueue#take 將會阻塞線程。

三、ThreadPoolExecutor#shutdownNow

ThreadPoolExecutor#shutdownNow 源碼如下:

你關(guān)閉線程池的方法安全嗎?

 

 

shutdownNow 方法將會把線程池狀態(tài)設(shè)置為 STOP,然后中斷所有線程,最后取出工作隊列中所有未完成的任務(wù)返回給調(diào)用者。

對比 shutdown 方法,shutdownNow 方法比較粗暴,直接中斷工作線程。不過這里需要注意,中斷線程并不代表線程立刻結(jié)束。這里需要線程主動配合線程中斷響應(yīng)。

線程中斷機制: thread#interrupt 只是設(shè)置一個中斷標(biāo)志,不會立即中斷正常的線程。如果想讓中斷立即生效,必須在線程 內(nèi)調(diào)用 Thread.interrupted() 判斷線程的中斷狀態(tài)。 對于阻塞的線程,調(diào)用中斷時,線程將會立刻退出阻塞狀態(tài)并拋出 InterruptedException 異常。所以對于阻塞線程需要正確處理 InterruptedException 異常。

 

awaitTermination

線程池 shutdown 與 shutdownNow 方法都不會主動等待執(zhí)行任務(wù)的結(jié)束,如果需要等到線程池任務(wù)執(zhí)行結(jié)束,需要調(diào)用 awaitTermination 主動等待任務(wù)調(diào)用結(jié)束。

調(diào)用方法如下:

你關(guān)閉線程池的方法安全嗎?

 

 

如果線程池任務(wù)執(zhí)行結(jié)束,awaitTermination 方法將會返回 true,否則當(dāng)?shù)却龝r間超過指定時間后將會返回 false。

如果需要使用這種進(jìn)制,建議在上面的基礎(chǔ)上增加一定重試次數(shù)。這個真的很重要!!!

四、優(yōu)雅關(guān)閉線程池

回顧上面線程池狀態(tài)關(guān)系圖,我們可以知道處于 SHUTDOWN 的狀態(tài)下的線程池依舊可以調(diào)用 shutdownNow。所以我們可以結(jié)合 shutdown , shutdownNow,awaitTermination ,更加優(yōu)雅關(guān)閉線程池。

你關(guān)閉線程池的方法安全嗎?

 

分享到:
標(biāo)簽:線程
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運動步數(shù)有氧達(dá)人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定