java高級應(yīng)用:線程池的全面講解(干貨)

什么是線程池?
很簡單,簡單看名字就知道是裝有線程的池子,我們可以把要執(zhí)行的多線程交給線程池來處理,和連接池的概念一樣,通過維護一定數(shù)量的線程池來達到多個線程的復(fù)用。
線程池的好處
我們知道不用線程池的話,每個線程都要通過new Thread(xxRunnable).start()的方式來創(chuàng)建并運行一個線程,線程少的話這不會是問題,而真實環(huán)境可能會開啟多個線程讓系統(tǒng)和程序達到最佳效率,當線程數(shù)達到一定數(shù)量就會耗盡系統(tǒng)的CPU和內(nèi)存資源,也會造成GC頻繁收集和停頓,因為每次創(chuàng)建和銷毀一個線程都是要消耗系統(tǒng)資源的,如果為每個任務(wù)都創(chuàng)建線程這無疑是一個很大的性能瓶頸。
所以,線程池中的線程復(fù)用極大節(jié)省了系統(tǒng)資源,當線程一段時間不再有任務(wù)處理時它也會自動銷毀,而不會長駐內(nèi)存。
線程池核心類
在java.util.concurrent包中我們能找到線程池的定義,其中ThreadPoolExecutor是我們線程池核心類,首先看看線程池類的主要參數(shù)有哪些。

corePoolSize:線程池的核心大小,也可以理解為最小的線程池大小。
maximumPoolSize:最大線程池大小。
keepAliveTime:空余線程存活時間,指的是超過corePoolSize的空余線程達到多長時間才進行銷毀。
unit:銷毀時間單位。
workQueue:存儲等待執(zhí)行線程的工作隊列。
threadFactory:創(chuàng)建線程的工廠,一般用默認即可。
handler:拒絕策略,當工作隊列、線程池全已滿時如何拒絕新任務(wù),默認拋出異常。
線程池工作流程
1、如果線程池中的線程小于corePoolSize時就會創(chuàng)建新線程直接執(zhí)行任務(wù)。
2、如果線程池中的線程大于corePoolSize時就會暫時把任務(wù)存儲到工作隊列workQueue中等待執(zhí)行。
3、如果工作隊列workQueue也滿時:當線程數(shù)小于最大線程池數(shù)maximumPoolSize時就會創(chuàng)建新線程來處理,而線程數(shù)大于等于最大線程池數(shù)maximumPoolSize時就會執(zhí)行拒絕策略。
線程池分類
Executors是jdk里面提供的創(chuàng)建線程池的工廠類,它默認提供了4種常用的線程池應(yīng)用,而不必我們?nèi)ブ貜?fù)構(gòu)造。
newFixedThreadPool
固定線程池,核心線程數(shù)和最大線程數(shù)固定相等,而空閑存活時間為0毫秒,說明此參數(shù)也無意義,工作隊列為最大為Integer.MAX_VALUE大小的阻塞隊列。當執(zhí)行任務(wù)時,如果線程都很忙,就會丟到工作隊列等有空閑線程時再執(zhí)行,隊列滿就執(zhí)行默認的拒絕策略。

newCachedThreadPool
帶緩沖線程池,從構(gòu)造看核心線程數(shù)為0,最大線程數(shù)為Integer最大值大小,超過0個的空閑線程在60秒后銷毀,SynchronousQueue這是一個直接提交的隊列,意味著每個新任務(wù)都會有線程來執(zhí)行,如果線程池有可用線程則執(zhí)行任務(wù),沒有的話就創(chuàng)建一個來執(zhí)行,線程池中的線程數(shù)不確定,一般建議執(zhí)行速度較快較小的線程,不然這個最大線程池邊界過大容易造成內(nèi)存溢出。

newSingleThreadExecutor
單線程線程池,核心線程數(shù)和最大線程數(shù)均為1,空閑線程存活0毫秒同樣無意思,意味著每次只執(zhí)行一個線程,多余的先存儲到工作隊列,一個一個執(zhí)行,保證了線程的順序執(zhí)行。

newScheduledThreadPool
調(diào)度線程池,即按一定的周期執(zhí)行任務(wù),即定時任務(wù),對ThreadPoolExecutor進行了包裝而已。

拒絕策略
AbortPolicy
簡單粗暴,直接拋出拒絕異常,這也是默認的拒絕策略。


CallerRunsPolicy
如果線程池未關(guān)閉,則會在調(diào)用者線程中直接執(zhí)行新任務(wù),這會導(dǎo)致主線程提交線程性能變慢。

DiscardPolicy
從方法看沒做任務(wù)操作,即表示不處理新任務(wù),即丟棄。

DiscardOldestPolicy
拋棄最老的任務(wù),就是從隊列取出最老的任務(wù)然后放入新的任務(wù)進行執(zhí)行。

如何提交線程
如可以先隨便定義一個固定大小的線程池
ExecutorService es = Executors.newFixedThreadPool(3);
提交一個線程
es.submit(xxRunnble); es.execute(xxRunnble);
submit和execute分別有什么區(qū)別呢?
execute沒有返回值,如果不需要知道線程的結(jié)果就使用execute方法,性能會好很多。
submit返回一個Future對象,如果想知道線程結(jié)果就使用submit提交,而且它能在主線程中通過Future的get方法捕獲線程中的異常。
如何關(guān)閉線程池
es.shutdown();
不再接受新的任務(wù),之前提交的任務(wù)等執(zhí)行結(jié)束再關(guān)閉線程池。
es.shutdownNow();
不再接受新的任務(wù),試圖停止池中的任務(wù)再關(guān)閉線程池,返回所有未處理的線程list列表。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
- Java簡單實現(xiàn)線程池
- Java多線程之線程池七個參數(shù)詳解
- Java利用線程工廠監(jiān)控線程池的實現(xiàn)示例
- Java 使用線程池執(zhí)行多個任務(wù)的示例
- 深入理解Java線程池從設(shè)計思想到源碼解讀
- 教你如何監(jiān)控 Java 線程池運行狀態(tài)的操作(必看)
- java多線程CountDownLatch與線程池ThreadPoolExecutor/ExecutorService案例
- java 線程池keepAliveTime的含義說明
- java并發(fā)包中CountDownLatch和線程池的使用詳解
- Java 線程池的作用以及該如何使用
- Java并發(fā)線程之線程池的知識總結(jié)
- Java線程池配置的一些常見誤區(qū)總結(jié)
- Java ExecutorServic線程池異步實現(xiàn)流程
- 淺談Java線程池是如何運行的
- java 優(yōu)雅關(guān)閉線程池的方案
- java中常見的6種線程池示例詳解
- 淺談Java線程池的7大核心參數(shù)
相關(guān)文章
IntelliJ IDEA 安裝教程2019.09.23(最新版)
本文通過圖文并茂的形式給大家介紹了IntelliJ IDEA 安裝教程2019.09.23最新版,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10
spring整合redis以及使用RedisTemplate的方法
本篇文章主要介紹了spring整合redis以及使用RedisTemplate的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05
Java實現(xiàn)簡單學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細介紹了Java實現(xiàn)簡單學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-07-07
Spring boot redis cache的key的使用方法
這篇文章主要介紹了Spring boot redis cache的key的使用方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧2019-05-05
基于Comparator對象集合實現(xiàn)多個條件按照優(yōu)先級的比較
這篇文章主要介紹了基于Comparator對象集合實現(xiàn)多個條件按照優(yōu)先級的比較,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07

