Java中的線程池ThreadPoolExecutor解析
線程池
針對各種池子,比如
- 連接池:用于管理和重復(fù)使用數(shù)據(jù)庫連接,避免頻繁創(chuàng)建和銷毀數(shù)據(jù)庫連接帶來的性能開銷。
- 對象池:用于管理和重復(fù)使用對象,避免頻繁創(chuàng)建和銷毀對象帶來的性能開銷。
- 字符串池:用于管理和重復(fù)使用字符串,避免頻繁創(chuàng)建和銷毀字符串帶來的性能開銷。
- 線程池的話也是一樣的,用于管理和重復(fù)使用線程,避免頻繁創(chuàng)建和銷毀線程帶來的性能開銷。
- 而線程池的工作原理就是相當(dāng)于把任務(wù)提交到一個(gè)阻塞隊(duì)列里面,如何線程去阻塞隊(duì)列里面拿到任務(wù)去執(zhí)行.
ThreadPoolExecutor詳解
首先看看UML圖:
可以看到最頂層的接口是Executor,就是線程池的頂層接口,線程池的作用就是執(zhí)行方法,而Executor方法里面就一個(gè)方法: void execute(Runnable command); 這個(gè)方法就是線程池最主要的方法,執(zhí)行runnable任務(wù),然后ExecutorService又對線程池的功能進(jìn)行了加強(qiáng),比如可以進(jìn)行管理線程池,且提供了執(zhí)行任務(wù)的能力,比如執(zhí)行異步返回Future結(jié)果的方法,執(zhí)行多個(gè)任務(wù)的方法;
ThreadPoolExecutor參數(shù)詳解
最主要的構(gòu)造方法:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
- int corePoolSize 核心線程數(shù)(一般為cpu數(shù)Runtime.getRuntime().availableProcessors())
- int maximumPoolSize 最大線程數(shù)(一般為cpu數(shù)*2)
- long keepAliveTime 存活的時(shí)長(<最大線程數(shù),<核心線程數(shù)的)
- TimeUnit 時(shí)間單位
- BlockingQueue workQueue 工作隊(duì)列
- ThreadFactory threadFactory 線程工廠,創(chuàng)建線程的地方
- RejectedExecutionHandler handler 拒絕策略
- 需要注意的是,maximumPoolSize 是當(dāng)線程隊(duì)列滿了,且核心線程都在執(zhí)行中的時(shí)候,再提交任務(wù),就不會放到隊(duì)列里面,只會新建線程執(zhí)行,如果線程數(shù)量等于了最大線程數(shù)的時(shí)候,就會走對應(yīng)的拒絕策略,如果任務(wù)執(zhí)行完,過期時(shí)間才會對新增線程有效,當(dāng)然有個(gè)方法allowCoreThreadTimeOut,讓核心線程也可以過期(一般不會設(shè)置的),一般工作隊(duì)列不會設(shè)置為無限隊(duì)列,因?yàn)槿绻?duì)列無限長可能會造成oom,且最大線程數(shù)就沒用了.
創(chuàng)建線程池的工具類Executors
- newFixedThreadPool
創(chuàng)建固定大小的線程池。核心數(shù)和最大數(shù)是一樣的,任務(wù)如果過多會在隊(duì)列中阻塞.如果某個(gè)線程因?yàn)閳?zhí)行異常而結(jié)束,那么線程池會補(bǔ)充一個(gè)新線程。
- newWorkStealingPool
1.8新加的線程池,forkJoinPool 可以根據(jù)CPU的核數(shù)并行的執(zhí)行,適合使用在很耗時(shí)的操作,可以充分的利用CPU執(zhí)行任務(wù),任務(wù)竊取線程池,不保證執(zhí)行順序,適合任務(wù)耗時(shí)差異較大。線程池中有多個(gè)線程隊(duì)列,有的線程隊(duì)列中有大量的比較耗時(shí)的任務(wù)堆積,而有的線程隊(duì)列卻是空的,就存在有的線程處于饑餓狀態(tài),當(dāng)一個(gè)線程處于饑餓狀態(tài)時(shí),它就會去其它的線程隊(duì)列中竊取任務(wù)。解決饑餓導(dǎo)致的效率問題。
默認(rèn)創(chuàng)建的并行 level 是 CPU 的核數(shù)。主線程結(jié)束,即使線程池有任務(wù)也會立即停止。
- newSingleThreadExecutor
創(chuàng)建一個(gè)單線程的線程池。這個(gè)線程池的核心數(shù)和最大數(shù)都是1,也就是相當(dāng)于單線程串行執(zhí)行所有任務(wù)。如果這個(gè)唯一的線程因?yàn)楫惓=Y(jié)束,那么會有一個(gè)新的線程來替代它。此線程池保證所有任務(wù)的執(zhí)行順序按照任務(wù)的提交順序執(zhí)行。
- newCachedThreadPool
創(chuàng)建一個(gè)可緩存的線程池。核心數(shù)是0,最大數(shù)是 Integer.MAX_VALUE,如果一下子任務(wù)很多,且執(zhí)行時(shí)間長,容易發(fā)生異常,堆溢出,且執(zhí)行效率降低,并不是線程數(shù)目越多,執(zhí)行越快的,如果線程池的大小超過了處理任務(wù)所需要的線程,那么就會回收部分空閑(60秒不執(zhí)行任務(wù))的線程,當(dāng)任務(wù)數(shù)增加時(shí),此線程池又可以智能的添加新線程來處理任務(wù)。此線程池不會對線程池大小做限制,線程池大小完全依賴于操作系統(tǒng)(或者說JVM)能夠創(chuàng)建的最大線程大小。
- newScheduledThreadPool
支持周期性任務(wù)的調(diào)度。此線程池支持定時(shí)以及周期性執(zhí)行任務(wù)的需求。按道理來說線程池的最大數(shù)是 Integer.MAX_VALUE,但是,線程數(shù)并不會超過核心數(shù)…是固定長度的.
這些方法基本都是創(chuàng)建ThreadPoolExecutor,或者繼承ThreadPoolExecutor,對其進(jìn)行增強(qiáng).
任務(wù)拒絕策略
默認(rèn)的拒絕策略是AbortPolicy,直接拋出異常
private static final RejectedExecutionHandler defaultHandler = new AbortPolicy(); public static class AbortPolicy implements RejectedExecutionHandler { /** * Creates an {@code AbortPolicy}. */ public AbortPolicy() { } /** * Always throws RejectedExecutionException. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task * @throws RejectedExecutionException always */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); } }
ThreadPoolExecutor.AbortPolicy 丟棄任務(wù)并且拋出- RejectedExecutionException異常。在任務(wù)不能提交的時(shí)候,拋出異常,及時(shí)反饋程序運(yùn)行狀態(tài)。如果是比較關(guān)鍵的業(yè)務(wù),推薦使用此拒絕策略,這樣子在系統(tǒng)不能承受更大的并發(fā)量的時(shí)候,能夠及時(shí)通過異常發(fā)現(xiàn)。
ThreadPoolExecutor.DiscardPolicy 丟棄任務(wù),但是不拋出異常。使用此策略,可能會使我們無法發(fā)現(xiàn)系統(tǒng)的異常狀態(tài)。建議是一些無關(guān)緊要的業(yè)務(wù)采用此策略。
ThreadPoolExecutor.DiscardOldestPolicy 丟棄隊(duì)列最前面的任務(wù),然后重新提交被拒絕的任務(wù)。
ThreadPoolExecutor.CallerRunsPolicy 由調(diào)用線程(提交任務(wù)的線程)處理該任務(wù)。這種情況是需要讓所有任務(wù)都執(zhí)行完畢,那么就適合大量計(jì)算的任務(wù)類型去執(zhí)行,多線程僅僅是增大吞吐量的手段,最終必須要讓每個(gè)任務(wù)都執(zhí)行完畢。
到此這篇關(guān)于Java中的線程池ThreadPoolExecutor解析的文章就介紹到這了,更多相關(guān)Java的ThreadPoolExecutor內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實(shí)現(xiàn)短信驗(yàn)證碼5分鐘有效時(shí)間
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)短信驗(yàn)證碼5分鐘有效時(shí)間,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07Springmvc國際化自動配置代碼實(shí)現(xiàn)
這篇文章主要介紹了Springmvc國際化自動配置代碼實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04SpringBoot+Quartz實(shí)現(xiàn)動態(tài)定時(shí)任務(wù)
這篇文章主要為大家詳細(xì)介紹了springBoot+Quartz實(shí)現(xiàn)動態(tài)定時(shí)任務(wù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09Mybatis的特點(diǎn)及優(yōu)點(diǎn)
Mybatis 本是apache的一個(gè)開源項(xiàng)目iBatis, 2010年這個(gè)項(xiàng)目由apache software foundation 遷移到了google code,并且改名為MyBatis。mybatis有哪些特點(diǎn)和優(yōu)點(diǎn)呢?通過本文一起學(xué)習(xí)吧2016-12-12