溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java線程池是怎么實現(xiàn)的

發(fā)布時間:2021-08-27 16:33:13 來源:億速云 閱讀:127 作者:chen 欄目:編程語言

這篇文章主要介紹“Java線程池是怎么實現(xiàn)的”,在日常操作中,相信很多人在Java線程池是怎么實現(xiàn)的問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java線程池是怎么實現(xiàn)的”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

  Java 線程池怎么玩

  想玩明白 Java 的線程池,只需要的知道構(gòu)建線程池的幾個參數(shù)具體的含義基本上就明了了。那么接下來,就讓我們一一瓦解這些參數(shù)。

  corePoolSize

  我們假設(shè)有 N 個任務(wù)需要提交到線程池去處理,當任務(wù)數(shù)量 N 小于核心線程數(shù) corePoolSize(后文用 C 來代替) 的時候,線程池會不斷新建線程來處理用戶提交進來的任務(wù)即使有線程空閑。C 其實代表的是線程池通常情況下會保留的線程數(shù)量(如果將線程池比作一個工廠,C 可以類比為工廠的正式編制人員數(shù)量),當任務(wù)數(shù)量 N 超過核心線程數(shù)量 C 的時候,線程池就要用到下一個參數(shù) workQueue 了。

  workQueue

  當用戶提交的任務(wù)數(shù)量變多了,這時候線程池中的線程數(shù)量已經(jīng)達到核心線程數(shù) C,那么只能將提交過來的任務(wù)暫存在 workQueue 隊列中。每當有線程處理完手頭上活的時候就會來工作隊列領(lǐng)取任務(wù),如果隊列中沒有任務(wù),那么當前線程就阻塞在隊列上,等待任務(wù)。工作隊列可以簡單分為 2 種:無界隊列和有界隊列。

  無界隊列

  如果我創(chuàng)建線程池的傳入的是無界隊列,那么意味著用戶可以源源不斷的提交任務(wù)到線程池,而不需要擔心線程池拒絕接收,例如 LinkedBlockingQueue 就是一種選擇。

  有界隊列

  如果我們傳入的是有界隊列,例如 ArrayBlockingQueue,那就需要考慮隊列存滿了怎么辦?不用擔心這個時候線程池會幫忙找一些臨時工來干活,這就需要用到下一個參數(shù) maximumPoolSize 了。

  maximumPoolSize

  此時所有的核心線程都在干活,而且工作隊列也存滿了任務(wù)。如果還是有任務(wù)提交進來,那么線程池會再創(chuàng)建新的線程來幫助工作(可以類比為一個工廠,管理員發(fā)現(xiàn)任務(wù)太多,倉庫也堆滿了任務(wù)需要雇傭一些臨時工來幫助干活)。當然臨時工也不能雇傭太多,畢竟工廠資源有限,需要設(shè)定工廠里面工人最大上限,這個就是 maximumPoolSize 了。然而瘋狂的用戶哪管你能不能處理完任務(wù),還是不斷的提交任務(wù)進來,這個時候線程池忍無可忍了,關(guān)門拒絕用戶提交新的任務(wù),這時候 RejectedExexcutionHandler 就要開始發(fā)揮作用了。

  RejectedExexcutionHandler

  線程池共提供了如下 4 種拒絕策略AbortPolicy 策略會拋出一個 RejectedExecutionException 異常給用戶,告訴它任務(wù)被拒絕了。DiscardPolicy 策略當任務(wù)來臨時候不會給用戶任何反饋,悄無聲息拒絕任務(wù)。DiscardOldestPolicy 策略比較霸道,它會直接將最早存儲在工作隊列的任務(wù)丟棄掉,然后再試圖去執(zhí)行當前提交進來的任務(wù)。CallerRunsPolicy 策略呢雖然線程池中的工人不幫忙處理任務(wù)了,它會占用用戶線程去處理當前任務(wù),這也就意味著用戶線程要處理完當前任務(wù)才可以做其他事情。

  使用上面的幾個核心參數(shù)完美的解決了任務(wù)的提交流程和工作分配問題,接下來就要來考慮一下后面的工作了。用戶提交了一大波任務(wù)以后,就不在提交了。這時候線程池的中工人都還在呢,如果一直保留這些資源但是又沒有活干,會造成資源的浪費。這時候就需要用到 keepAliveTime 和 TimeUnit 參數(shù)了。

  keepAliveTime 和 TimeUnit

  這 2 個參數(shù)組合起來決定了一個工人最多可以在工廠里愉快的摸魚時間,如果摸魚時間超過這個限度,這個工人資源就會被釋放,也就是這個空閑線程資源就被回收掉咯。當然啦,線程池會保留核心線程在工廠里面等待新任務(wù),以備有新任務(wù)的到來,我們也可以通過 public void allowCoreThreadTimeOut(boolean value) 方法設(shè)置參數(shù),來允許線程池也可以釋放核心線程。

  threadFactory

  還剩下最后一個參數(shù),它比較簡單,主要用來創(chuàng)建線程,例如我們想讓線程池中的線程做一些定制化的工作就可以自己來定義線程工廠,這樣線程池創(chuàng)建線程的時候就使用我們指定的工廠了。

  你可能會覺得構(gòu)建一個線程還要設(shè)置這么參數(shù),太麻煩了,貼心的 JDK 幫我們在 Executors 中準備了幾個靜態(tài)工廠方法,我們一起看一下它們的特性:newFixedThreadPool(int nThreads) 可以創(chuàng)建一個固定線程數(shù)量的線程池,同時它的工作隊列是一個無界隊列。newSingleThreadExecutor() 可以創(chuàng)建只有一個線程工作的線程池,同時它的工作隊列也是無界隊列。newCachedThreadPool() 可以創(chuàng)建一個沒上限工作線程的線程池,它使用了 SynchronousQueue 只要有任務(wù)過來,如果有空閑的線程,會優(yōu)先利用空閑的線程池,沒有空閑線程就會新創(chuàng)建線程。newSingleThreadScheduledExecutor() 創(chuàng)建的是一個具有延遲和循環(huán)執(zhí)行任務(wù)線程池,同時它內(nèi)部也只有一個線程,它的工作隊列是一個具有延遲功能的隊列 DelayedWorkQueue。newWorkStealingPool() 這種方法是 Java 8 提供的,它實際創(chuàng)建的是一個 ForkJoinTool 而不是 ThreadPoolExecutor 的實例。如上即為 5 中創(chuàng)建線程池的工廠方法,大家根據(jù)需要選擇適合自己工作的,當然也可以直接使用 ThreadPoolExecutor 來創(chuàng)建一個。

到此,關(guān)于“Java線程池是怎么實現(xiàn)的”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI