您好,登錄后才能下訂單哦!
這篇文章主要講解了“什么是線程池”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“什么是線程池”吧!
(I:代表接口,C:代表實(shí)現(xiàn)類)I:Executor I:ExecutorService C:AbstractExecutorService C:ThreadPoolExecutor
該類的主要構(gòu)造函數(shù)如下:
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
corePoolSize:核心線程池的大小。如果核心線程池有空閑位置,新的任務(wù)進(jìn)來就會被核心線程池新建一個(gè)線程執(zhí)行,執(zhí)行完畢后不會銷毀線程,線程會進(jìn)入緩存隊(duì)列等待再次被運(yùn)行。
maximunPoolSize:最大的線程數(shù)量。如果核心線程池和緩存隊(duì)列都已經(jīng)滿了,新的任務(wù)進(jìn)來就會創(chuàng)建新的線程來執(zhí)行。但是數(shù)量不能超過maximunPoolSize,否側(cè)會采取拒絕接受任務(wù)策略,我們下面會具體分析。
keepAliveTime:非核心線程能夠空閑的最長時(shí)間,超過時(shí)間,線程終止。這個(gè)參數(shù)默認(rèn)只有在線程數(shù)量超過核心線程池大小時(shí)才會起作用。只要線程數(shù)量不超過核心線程大小,就不會起作用。
unit:時(shí)間單位,和keepAliveTime配合使用。
workQueue: 緩存隊(duì)列,用來存放等待被執(zhí)行的任務(wù),有以下取值:
1、ArrayBlockingQueue; 有界阻塞隊(duì)列,詳見文章:ArrayBlockingQueue詳解
2、LinkedBlockingQueue; 無界阻塞隊(duì)列,詳見文章:LinkedBlockingQueue詳解
3、SynchronousQueue; 無緩沖阻塞隊(duì)列 ,詳見文章:SynchronousQueue詳解
threadFactory:線程工廠,用來創(chuàng)建線程,默認(rèn)new Executors.DefaultThreadFactory();
handler: 線程拒絕策略。當(dāng)創(chuàng)建的線程超出maximumPoolSize值,且緩沖隊(duì)列已滿時(shí),對新提交任務(wù)的處理策略,有以下4種取值,我們結(jié)合代碼分析
1、ThreadPoolExecutor.AbortPolicy 無視任務(wù)(也就是丟棄任務(wù)),并通過拋異常告知調(diào)用者“我拒絕接收新任務(wù)”
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { //這里直接拋出異常,可理解為:無視任務(wù)(也就是丟棄任務(wù)),并通過拋異常告知調(diào)用者“我拒絕接收新任務(wù)” throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); }
2、ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù),但是不做任何處理。
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { //這里是空實(shí)現(xiàn),也就是丟棄任務(wù),不作任何的處理 //這會導(dǎo)致:雖然此策略被觸發(fā),但調(diào)用者根本不知道它提交進(jìn)來的任務(wù),最終到底有沒有被執(zhí)行 }
3、ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊(duì)列最前面的任務(wù),嘗試執(zhí)行新任務(wù)。
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { //判斷線程池是否被關(guān)閉了 e.getQueue().poll();//丟棄隊(duì)列最前面的任務(wù) e.execute(r); //嘗試執(zhí)行新任務(wù) } }
4、ThreadPoolExecutor.CallerRunsPolicy:由調(diào)用線程處理該任務(wù)
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { //判斷線程池是否被關(guān)閉了 r.run(); //調(diào)用線程直接調(diào)用run()方法,執(zhí)行其代碼邏輯 } }
基于ThreadPoolExecutor 的構(gòu)造參數(shù)如此之多,JDK為我們提供了Executors類,通過它我們可以簡單的創(chuàng)建出四種類型的線程池,一般場景下夠用了。
1.3.1、固定大小線程池
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor( nThreads, // corePoolSize nThreads,// maximumPoolSize 0L, TimeUnit.MILLISECONDS,// keepAliveTime=0秒 new LinkedBlockingQueue<Runnable>()// 利用無界阻塞隊(duì)列 ); }
參數(shù):corePoolSize = 固定值,maximumPoolSize = 固定值,keepAliveTime = 0秒 ,workQueue = LinkedBlockingQueue 無界阻塞隊(duì)列
分析:
1、corePoolSize 和 maximumPoolSize 都為 nThreads 一個(gè)固定值,說明此線程池中都是核心線程,keepAliveTime為非核心線程空閑時(shí)間,該線程池中不存在非核心線程,所以參數(shù)keepAliveTime在此處無效;
2、new LinkedBlockingQueue<Runnable>() :緩存隊(duì)列用的無界阻塞隊(duì)列,當(dāng)核心池子里的線程都在忙的時(shí)候,新進(jìn)來的任務(wù)被放到此隊(duì)列中;一旦有空閑的線程了,該線程就會從隊(duì)列里去拿任務(wù)執(zhí)行;
3、缺點(diǎn):因?yàn)橛玫氖菬o界隊(duì)列,所以當(dāng) nThreads 個(gè)線程一直被占用的情況下,同時(shí)又不斷的有新任務(wù)進(jìn)來,就有可能導(dǎo)致OOM問題;
1.3.2、單個(gè)線程的線程池
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, // corePoolSize,maximumPoolSize 0L, TimeUnit.MILLISECONDS,// keepAliveTime=0秒 new LinkedBlockingQueue<Runnable>())// 利用無界阻塞隊(duì)列 ); }
參數(shù):corePoolSize = 1,maximumPoolSize = 1,keepAliveTime = 0秒 ,workQueue = LinkedBlockingQueue 無界阻塞隊(duì)列
分析:
1、corePoolSize 和 maximumPoolSize 都為1,此線程池只有一個(gè)核心線程,同上,參數(shù)keepAliveTime在此處無效;
2、new LinkedBlockingQueue<Runnable>() :緩存隊(duì)列用的無界阻塞隊(duì)列,當(dāng)僅有的一個(gè)核心線程在忙的時(shí)候,新進(jìn)來的任務(wù)被放到此隊(duì)列中;待線程空閑了,就會從隊(duì)列里去拿任務(wù)執(zhí)行;
3、缺點(diǎn):因?yàn)橛玫氖菬o界隊(duì)列,所以當(dāng)核心線程一直被占用的情況下,同時(shí)又不斷的有新任務(wù)進(jìn)來,就有可能導(dǎo)致OOM問題;
4、有沒有注意到,這里為什么用了一個(gè)FinalizableDelegatedExecutorService類呢?
見文章:關(guān)于newSingleThreadExecutor中的FinalizableDelegatedExecutorService源碼分析
1.3.3、緩存線程池
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE,// corePoolSize,maximumPoolSize 60L, TimeUnit.SECONDS,// keepAliveTime=60秒 new SynchronousQueue<Runnable>());// 同步阻塞隊(duì)列 }
參數(shù):corePoolSize = 0,maximumPoolSize = 無限大,keepAliveTime = 60秒(重要) ,workQueue = SynchronousQueue 無緩沖阻塞隊(duì)列
分析:一個(gè)可以根據(jù)需要?jiǎng)?chuàng)建線程的線程池,此線程池中所有線程都為非核心線程,且最大空閑時(shí)間為60秒,最多可以創(chuàng)建Integer.MAX_VALUE 個(gè)線程(2^31次方,21億多,可以視為無限);SynchronousQueue 為無緩沖阻塞隊(duì)列,也就是此隊(duì)列里不會緩沖新的任務(wù),有新任務(wù)進(jìn)來時(shí),如果無空閑線程,就會新創(chuàng)建一個(gè)線程;如果有空閑線程,就會使用空閑線程;所以此線程池適合執(zhí)行一些執(zhí)行周期短的任務(wù)。
感謝各位的閱讀,以上就是“什么是線程池”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對什么是線程池這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。