Java并發(fā)線程之線程池的知識(shí)總結(jié)
初始化線程池后,把任務(wù)丟進(jìn)去,等待調(diào)度就可以了,使用起來(lái)比較方便。
JAVA中Thread是線程類,不建議直接使用Thread執(zhí)行任務(wù),在并發(fā)數(shù)量比較多的情況下,每個(gè)線程都是執(zhí)行一個(gè)很短的時(shí)間就任務(wù)結(jié)束了,這樣頻繁創(chuàng)建線程會(huì)大大降低系統(tǒng)的效率,因?yàn)轭l繁的創(chuàng)建和銷毀線程需要時(shí)間。而線程池可以復(fù)用,就是執(zhí)行完一個(gè)任務(wù),并不銷毀,而是可以繼續(xù)執(zhí)行其它任務(wù)。
Thread的弊端
- 每次
new Thread()
創(chuàng)建對(duì)象,性能差。 - 線程缺乏統(tǒng)一管理,可能無(wú)限制創(chuàng)建線程,相互競(jìng)爭(zhēng),有可能占用過(guò)多系統(tǒng)資源導(dǎo)致死機(jī)或OOM。
- 不能多執(zhí)行,定期執(zhí)行,線程中斷
線程池的優(yōu)點(diǎn)
- 重用存在的線程,減少對(duì)象創(chuàng)建,消亡的開(kāi)銷,性能佳,降低資源消耗。
- 可以控制最大并發(fā)線程數(shù),提高系統(tǒng)資源利用率,同時(shí)避免過(guò)多資源競(jìng)爭(zhēng),避免阻塞,提高響應(yīng)速度。
- 提供定時(shí)執(zhí)行,定期執(zhí)行,單線程,并發(fā)數(shù)控制等功能,以提高線程的可管理性。
阿里發(fā)布的 Java 開(kāi)發(fā)手冊(cè)中強(qiáng)制線程池不允許使用 Executors 去創(chuàng)建,而是通過(guò) ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同學(xué)更加明確線程池的運(yùn)行規(guī)則,規(guī)避資源耗盡的風(fēng)險(xiǎn)。
Executors利用工廠模式向我們提供了4種線程池實(shí)現(xiàn)方式,但是并不推薦使用,原因是使用Executors創(chuàng)建線程池不會(huì)傳入相關(guān)參數(shù)而使用默認(rèn)值所以我們常常忽略了那些重要的參數(shù)(線程池大小、緩沖隊(duì)列的類型等),而且默認(rèn)使用的參數(shù)會(huì)導(dǎo)致資源浪費(fèi),不可取。
ThreadPoolExecutor介紹
構(gòu)造函數(shù)和參數(shù)
java.uitl.concurrent.ThreadPoolExecutor類是線程池中最核心的一個(gè)類。
public class ThreadPoolExecutor extends AbstractExecutorService { /** 構(gòu)造函數(shù) 1 */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {} /** 構(gòu)造函數(shù) 2 */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {} /** 構(gòu)造函數(shù) 3 */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {} /** 構(gòu)造函數(shù) 4 */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {} }
ThreadPoolExecutor類中提供了四個(gè)構(gòu)造方法,在構(gòu)造函數(shù)4中,參數(shù)最多,通過(guò)觀察其他3個(gè)構(gòu)造函數(shù),發(fā)現(xiàn)前面三個(gè)構(gòu)造器都是調(diào)用的第四個(gè)構(gòu)造器進(jìn)行的初始化工作。
構(gòu)造器中各個(gè)參數(shù)的含義
corePoolSize 核心線程池的大小,在創(chuàng)建了線程池后,默認(rèn)情況下,線程池中沒(méi)有任何的線程池,而是等任務(wù)過(guò)來(lái)了再去創(chuàng)建線程執(zhí)行任務(wù)。除非調(diào)用了預(yù)創(chuàng)建線程的方法,即在沒(méi)有任務(wù)到來(lái)之前就創(chuàng)建corePoolSize個(gè)線程或者一個(gè)線程。當(dāng)線程池中的線程數(shù)量到達(dá)corePoolSize后,就會(huì)把到達(dá)的任務(wù)放到緩存隊(duì)列里面。
- prestartCoreThread() : 預(yù)創(chuàng)建一個(gè)核心線程,使其閑置等待工作。
- prestartAllCoreThreads() : 啟動(dòng)所有核心線程,導(dǎo)致它們空閑地等待工作。
maxnumPoolSize 線程池中最大的線程數(shù),是一個(gè)非常重要的參數(shù),它表示在線程池中最多能創(chuàng)建多少線程。
keepAliveTime 表示線程在沒(méi)有任務(wù)執(zhí)行時(shí)最多保持多久時(shí)間會(huì)終止。默認(rèn)情況下,只有當(dāng)線程池中的線程數(shù)大于corePoolSize
時(shí),keepAliveTime
才會(huì)起作用,即當(dāng)線程池中的線程數(shù)大于corePoolSize
,如果一個(gè)線程的空閑時(shí)間達(dá)到keepAliveTime
,則會(huì)終止直到線程池中的線程數(shù)量不大于corePoolSize
。但是如果調(diào)用了allowCoreThreadTimeOut(boolean)
方法,在線程池中線程數(shù)不大于corePoolSize
時(shí),keepAliveTime
參數(shù)也會(huì)啟作用,直到線程池中的線程數(shù)為0。unit 參數(shù)
keepAliveTime
的時(shí)間單位,有7種取值,在TimeUnit
類中有7種靜態(tài)屬性。
- TimeUnit.DAYS : 以 天 為單位 ;
- TimeUnit.HOURS : 以 小時(shí) 為單位 ;
- TimeUnit.MINUTES : 以 分鐘 為單位 ;
- TimeUnit.SECONDS : 以 秒 為單位 ;
- TimeUnit.MILLISECONDS : 以 毫秒 為單位 ;
- TimeUnit.MICROSECONDS : 以 微秒 為單位 ;
- TimeUnit.NANOSECONDS : 以 納秒 為單位 ;
workQueue一個(gè)阻塞隊(duì)列,用來(lái)存儲(chǔ)等待執(zhí)行的任務(wù),這個(gè)參數(shù)的選擇也很重要,會(huì)對(duì)線程池的運(yùn)行過(guò)程產(chǎn)生重大影響,一般有以下幾種選擇。
- ArrayBlockingQueue:基于數(shù)組的先進(jìn)先出隊(duì)列,創(chuàng)建時(shí)必須指定大小。
- LinkedBlockingQueue:基于鏈表的先進(jìn)先出隊(duì)列,若果創(chuàng)建時(shí)沒(méi)有指定此隊(duì)列的大小,則默認(rèn)為
Integer.MAX_VALUE
。 - SynchronousQueue:這個(gè)隊(duì)列比較特殊,它不會(huì)保存提交的任務(wù),而是直接新建一個(gè)線程來(lái)執(zhí)行新的任務(wù)。
threadFactory線程工廠,主要用來(lái)創(chuàng)建線程。線程池最重要的一項(xiàng)工作,就是在滿足某些條件情況下創(chuàng)建線程。在
ThreadPoolExecutor
線程池中,創(chuàng)建線程的操作時(shí)交給ThreadFactoty
來(lái)完成。使用線程池,就必須要指定threadFactory
。如果我們的構(gòu)造器中沒(méi)有指定使用ThreadFactory
,這個(gè)時(shí)候ThreadPoolExecutor
就會(huì)使用默認(rèn)的ThreadFactory:DefaultThreadFactory
handler 在ThreadPoolExecutor線程池中還有一個(gè)重要的接口:RejectedExecutionHandler。當(dāng)提交給線程池的某一個(gè)新任務(wù)無(wú)法直接被線程池中“核心線程”直接處理,又無(wú)法加入等待隊(duì)列,也無(wú)法創(chuàng)建新的線程執(zhí)行;又或者線程池已經(jīng)調(diào)用shutdown()方法停止了工作;又或者線程池不是處于正常的工作狀態(tài);這時(shí)候ThreadPoolExecutor線程池會(huì)拒絕處理這個(gè)任務(wù),觸發(fā)創(chuàng)建ThreadPoolExecutor線程池時(shí)定義的RejectedExecutionHandler接口的實(shí)現(xiàn),表示當(dāng)拒絕處理任務(wù)時(shí)的策略,有以下四種取值,四種值都為其靜態(tài)內(nèi)部類:
- ThreadPoolExecutor.AbortPolicy:丟棄任務(wù)并拋出RejectedExecutionException異常
- ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù),但是不拋出異常。
- ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊(duì)列最前面的任務(wù),然后重新嘗試執(zhí)行新提交的任務(wù)。
ThreadPoolExecutor執(zhí)行execute方法分下面4種情況
- 如果當(dāng)前運(yùn)行的線程少于
corePoolSize
,則創(chuàng)建新的線程來(lái)執(zhí)行任務(wù)(執(zhí)行這一步驟需要獲取全局鎖) - 如果運(yùn)行的線程等于或者多于
corePoolSize
,則將任務(wù)加入到BlockingQueue
- 如果無(wú)法將任務(wù)加入
BlockingQueue
(隊(duì)列已滿),則創(chuàng)建新的線程來(lái)處理任務(wù)(執(zhí)行這一步驟需要獲取全局鎖) - 如果創(chuàng)建新線程將當(dāng)前運(yùn)行的線程超出
maxnumPoolSize
,任務(wù)被拒絕,并調(diào)用RejectedExecutionHandler.rejectedExecution()
方法。
以上就是Java并發(fā)線程之線程池的知識(shí)總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Java 線程池的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解析SpringSecurity自定義登錄驗(yàn)證成功與失敗的結(jié)果處理問(wèn)題
這篇文章主要介紹了SpringSecurity系列之自定義登錄驗(yàn)證成功與失敗的結(jié)果處理問(wèn)題,本文通過(guò)實(shí)例給大家講解的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11JavaWeb Session 會(huì)話管理實(shí)例詳解
這篇文章主要介紹了JavaWeb Session 會(huì)話管理的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧2016-09-09Java 詳細(xì)講解分治算法如何實(shí)現(xiàn)歸并排序
分治算法的基本思想是將一個(gè)規(guī)模為N的問(wèn)題分解為K個(gè)規(guī)模較小的子問(wèn)題,這些子問(wèn)題相互獨(dú)立且與原問(wèn)題性質(zhì)相同。求出子問(wèn)題的解,就可得到原問(wèn)題的解,本篇文章我們就用分治算法來(lái)實(shí)現(xiàn)歸并排序2022-04-04Java中properties文件中的中文亂碼問(wèn)題
Properties為了方便用戶的配置,用于讀取Java的配置文件,不同的編程語(yǔ)言有自己所支持的配置文件,能讓用戶夠脫離程序本身去修改相關(guān)的變量設(shè)置,這篇文章主要介紹了Java中properties文件中的中文亂碼問(wèn)題,需要的朋友可以參考下2023-08-08淺談Map集合中g(shù)et不存在的key值,會(huì)拋出異常嗎?
這篇文章主要介紹了淺談Map集合中g(shù)et不存在的key值,會(huì)拋出異常嗎?具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09Java動(dòng)態(tài)追蹤技術(shù)探究之從JSP到Arthas
這篇文章主要介紹了Java動(dòng)態(tài)追蹤技術(shù)探究之從JSP到Arthas,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下2019-06-06解決Eclipse Tomcat OutOfMemoryError:PermGen space的問(wèn)題
今天小編就為大家分享一篇關(guān)于解決Eclipse Tomcat OutOfMemoryError:PermGen space的問(wèn)題,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12