java 線程池

ThreadPoolExecutor 用于創(chuàng)建線程池,它有 4 個(gè)重載構(gòu)造器,我們以最多參數(shù)的構(gòu)造器講解:

ThreadPoolExecutor(int corePoolSize,                    # 線程池核心線程個(gè)數(shù),默認(rèn)線程池線程個(gè)數(shù)為 0,只有接到任務(wù)才新建線程
                   int maximumPoolSize,                 # 線程池最大線程數(shù)量
                   long keepAliveTime,                  # 線程池空閑時(shí),線程存活的時(shí)間,當(dāng)線程池中的線程數(shù)大于 corePoolSize 時(shí)才會(huì)起作用
                   TimeUnit unit,                       # 時(shí)間單位
                   BlockingQueue<Runnable> workQueue,   # 阻塞隊(duì)列,當(dāng)達(dá)到線程數(shù)達(dá)到 corePoolSize 時(shí),將任務(wù)放入隊(duì)列等待線程處理
                   ThreadFactory threadFactory,         # 線程工廠
                   RejectedExecutionHandler handler)    # 線程拒絕策略,當(dāng)隊(duì)列滿了并且線程個(gè)數(shù)達(dá)到 maximumPoolSize 后采取的策略

阻塞隊(duì)列有以下 4 種:

ArrayBlockingQueue:基于數(shù)組、有界,按 FIFO(先進(jìn)先出)原則對(duì)元素進(jìn)行排序;
LinkedBlockingQueue:基于鏈表,按FIFO (先進(jìn)先出) 排序元素,吞吐量通常要高于 ArrayBlockingQueue;
SynchronousQueue:每個(gè)插入操作必須等到另一個(gè)線程調(diào)用移除操作,否則插入操作一直處于阻塞狀態(tài),吞吐量通常要高于 LinkedBlockingQueue;
PriorityBlockingQueue:具有優(yōu)先級(jí)的、無(wú)限阻塞隊(duì)列。

線程拒絕策略有以下 4 種:

CallerRunsPolicy:如果發(fā)現(xiàn)線程池還在運(yùn)行,就直接運(yùn)行這個(gè)線程;
DiscardOldestPolicy:在線程池的等待隊(duì)列中,將頭取出一個(gè)拋棄,然后將當(dāng)前線程放進(jìn)去;
DiscardPolicy:默默丟棄,不拋出異常;
AbortPolicy:java默認(rèn),拋出一個(gè)異常(RejectedExecutionException)。

實(shí)現(xiàn)原則:

如果當(dāng)前池大小 poolSize 小于 corePoolSize ,則創(chuàng)建新線程執(zhí)行任務(wù);
如果當(dāng)前池大小 poolSize 大于 corePoolSize ,且等待隊(duì)列未滿,則進(jìn)入等待隊(duì)列;
如果當(dāng)前池大小 poolSize 大于 corePoolSize 且小于 maximumPoolSize ,且等待隊(duì)列已滿,則創(chuàng)建新線程執(zhí)行任務(wù);
如果當(dāng)前池大小 poolSize 大于 corePoolSize 且大于 maximumPoolSize ,且等待隊(duì)列已滿,則調(diào)用拒絕策略來(lái)處理該任務(wù);
線程池里的每個(gè)線程執(zhí)行完任務(wù)后不會(huì)立刻退出,而是會(huì)去檢查下等待隊(duì)列里是否還有線程任務(wù)需要執(zhí)行,如果在 keepAliveTime 里等不到新的任務(wù)了,那么線程就會(huì)退出。

2.2.3 內(nèi)置線程池

在 java.util.concurrent 包中已經(jīng)提供為大多數(shù)使用場(chǎng)景的內(nèi)置線程池:

Executors.newSingleThreadExecutor()     # 單條線程
Executors.newFixedThreadPool(int n)     # 固定數(shù)目線程的線程池
Executors.newCachedThreadPool()         # 創(chuàng)建一個(gè)可緩存的線程池,調(diào)用execute 將重用以前構(gòu)造的線程(如果線程可用)。如果現(xiàn)有線程沒(méi)有可用的,則創(chuàng)建一個(gè)新線程并添加到池中。終止并從緩存中移除那些已有 60 秒鐘未被使用的線程。
Executors.newScheduledThreadPool(int n) # 支持定時(shí)及周期性的任務(wù)執(zhí)行的線程池,多數(shù)情況下可用來(lái)替代 Timer 類。

上述 4 種線程池底層都是通過(guò)創(chuàng)建 ThreadPoolExecutor 獲取線程池。

  1. newSingleThreadExecutor
    主要用于串行(順序執(zhí)行)操作場(chǎng)景。

  2. newFixedThreadPool
    主要用于負(fù)載比較重的場(chǎng)景,為了資源的合理利用,需要限制當(dāng)前線程數(shù)量。

  3. newCachedThreadPool
    主要用于并發(fā)執(zhí)行大量短期的小任務(wù),或者是負(fù)載較輕的服務(wù)器。

  4. newScheduledThreadPool
    ScheduledExecutorService 繼承 ThreadPoolExecutor。

2.2.4 提交任務(wù)

獲取 ExecutorService 對(duì)象后,我們需要提交任務(wù)來(lái)讓線程池中的線程執(zhí)行,提交任務(wù)的方法有 2 種:

       #  void execute():提交不需要返回值的任務(wù)
       pool.execute(() -> System.out.println("1L"));
       # Future<T> submit(): 提交需要返回值的任務(wù)
        Future<Long> future = pool.submit(() -> {
            System.out.println("1L");
            return 1L;
        });
        Long result = future.get();
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容