Java線程池二JDK提供的線程池工廠方法

Executors

要配置線程池是比較復(fù)雜的,在對于線程池的原理不是很清楚的情況下
很有可能配置的線程池不是較優(yōu)的,我們可以參考看一些框架是如何使用線程池的

因此在Executors類里面提供了一些靜態(tài)工廠,生成一些常用的線程池。

線程池可以解決兩個(gè)不同問題:
由于減少了每個(gè)任務(wù)調(diào)用的開銷,它們通??梢栽趫?zhí)行大量異步任務(wù)時(shí)提供增強(qiáng)的性能,
并且還可以提供綁定和管理資源(包括執(zhí)行任務(wù)集時(shí)使用的線程)的方法。
每個(gè) ThreadPoolExecutor 還維護(hù)著一些基本的統(tǒng)計(jì)數(shù)據(jù),如完成的任務(wù)數(shù)。

為了便于跨大量上下文使用,此類提供了很多可調(diào)整的參數(shù)和擴(kuò)展鉤子 (hook)。
但是,強(qiáng)烈建議程序員使用較為方便的 Executors 工廠方法

Executors.newCachedThreadPool()(無界線程池,可以進(jìn)行自動(dòng)線程回收)

Executors.newFixedThreadPool(int)(固定大小線程池)

Executors.newSingleThreadExecutor()(單個(gè)后臺(tái)線程)

它們均為大多數(shù)使用場景預(yù)定義了設(shè)置。否則,在手動(dòng)配置和調(diào)整此類時(shí),使用以下指導(dǎo):
核心和最大池大小 ThreadPoolExecutor 將根據(jù) corePoolSize(參見 getCorePoolSize())
和 maximumPoolSize(參見 getMaximumPoolSize())設(shè)置的邊界自動(dòng)調(diào)整池大小。

當(dāng)新任務(wù)在方法 execute(java.lang.Runnable) 中提交時(shí):
如果運(yùn)行的線程少于 corePoolSize,則創(chuàng)建新線程來處理請求,即使其他輔助線程是空閑的。
如果運(yùn)行的線程多于 corePoolSize 而少于 maximumPoolSize,則僅當(dāng)隊(duì)列滿時(shí)才創(chuàng)建新線程。
如果設(shè)置的 corePoolSize 和 maximumPoolSize 相同,則創(chuàng)建了固定大小的線程池。
如果將 maximumPoolSize 設(shè)置為基本的無界值(如 Integer.MAX_VALUE),則允許池適應(yīng)任意數(shù)量的并發(fā)任務(wù)。

在大多數(shù)情況下,核心和最大池大小僅基于構(gòu)造來設(shè)置,
不過也可以使用 setCorePoolSize(int) 和 setMaximumPoolSize(int) 進(jìn)行動(dòng)態(tài)更改。
按需構(gòu)造 默認(rèn)情況下,即使核心線程最初只是在新任務(wù)到達(dá)時(shí)才創(chuàng)建和啟動(dòng)的,
也可以使用方法 prestartCoreThread() 或 prestartAllCoreThreads() 對其進(jìn)行動(dòng)態(tài)重寫

1、 newSingleThreadExecutor

//核心線程數(shù)和最大線程數(shù)都是1,隊(duì)列為無界隊(duì)列,只有一個(gè)線程存活時(shí)間沒有意義
new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>())

創(chuàng)建一個(gè)單線程的線程池。這個(gè)線程池只有一個(gè)線程在工作,也就是相當(dāng)于單線程串行執(zhí)行所有任務(wù)。
如果這個(gè)唯一的線程因?yàn)楫惓=Y(jié)束,那么會(huì)有一個(gè)新的線程來替代它。
此線程池保證所有任務(wù)的執(zhí)行順序按照任務(wù)的提交順序執(zhí)行。

2、newFixedThreadPool

//核心線程數(shù)等于最大線程數(shù),隊(duì)列為無界隊(duì)列
new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>())

創(chuàng)建固定大小的線程池。每次提交一個(gè)任務(wù)就創(chuàng)建一個(gè)線程,直到線程達(dá)到線程池的最大大小。線程池的大小一旦達(dá)到最大值就會(huì)保持不變,如果某個(gè)線程因?yàn)閳?zhí)行異常而結(jié)束,那么線程池會(huì)補(bǔ)充一個(gè)新線程。

class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"----"+i);
        }
    }
}

        ExecutorService pool =  Executors.newFixedThreadPool(2);
        pool.submit(new MyRunnable());
        pool.submit(new MyRunnable());
運(yùn)行結(jié)果

不禁要問 newSingleThreadExecutor不就是newFixedThreadPool(1)嗎?
API文檔中有說明,其實(shí)最好的還是看代碼吧
newSingleThreadExecutor返回的是FinalizableDelegatedExecutorService
被裝飾過的ThreadPoolExecutor,已經(jīng)調(diào)用不到ThreadPoolExecutor的方法了

//newSingleThreadExecutor 不能配置去重新加入線程;
// final ExecutorService single = Executors.newSingleThreadExecutor();
   final ExecutorService fixed = Executors.newFixedThreadPool(1);
   ThreadPoolExecutor executor = (ThreadPoolExecutor) fixed;
   executor.setCorePoolSize(4);

3、 newCachedThreadPool

new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());

創(chuàng)建一個(gè)可緩存的線程池。如果線程池的大小超過了處理任務(wù)所需要的線程,
那么就會(huì)回收部分空閑(60秒不執(zhí)行任務(wù))的線程,當(dāng)任務(wù)數(shù)增加時(shí),此線程池又可以智能的添加新線程來處理任務(wù)。此線程池不會(huì)對線程池大小做限制,線程池大小完全依賴于操作系統(tǒng)(或者說JVM)能夠創(chuàng)建的最大線程大小。

4、newScheduledThreadPool
創(chuàng)建一個(gè)大小無限的線程池。此線程池支持定時(shí)以及周期性執(zhí)行任務(wù)的需求。

submit和execute的區(qū)別

  1. 接收的參數(shù)不一樣,submit可接收callback,有幾個(gè)重載的方法
  2. submit有返回值, execute沒有

shutdown和shutdownNow

  • shutdown()
    按過去執(zhí)行已提交任務(wù)的順序發(fā)起一個(gè)有序的關(guān)閉,但是不接受新任務(wù)
    如果已經(jīng)關(guān)閉,則調(diào)用沒有其他作用

  • List<Runnable> shutdownNow()
    嘗試停止所有的活動(dòng)執(zhí)行任務(wù)、暫停等待任務(wù)的處理,并返回等待執(zhí)行的任務(wù)列表
    在從此方法返回的任務(wù)隊(duì)列中排空(移除)這些任務(wù)。 并不保證能夠停止正在處理的活動(dòng)執(zhí)行任務(wù)
    但是會(huì)盡力嘗試。 此實(shí)現(xiàn)通過 Thread.interrupt() 取消任務(wù)
    所以無法響應(yīng)中斷的任何任務(wù)可能永遠(yuǎn)無法終止

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 為什么使用線程池 當(dāng)我們在使用線程時(shí),如果每次需要一個(gè)線程時(shí)都去創(chuàng)建一個(gè)線程,這樣實(shí)現(xiàn)起來很簡單,但是會(huì)有一個(gè)問題...
    閩越布衣閱讀 4,420評(píng)論 10 45
  • 本文是我自己在秋招復(fù)習(xí)時(shí)的讀書筆記,整理的知識(shí)點(diǎn),也是為了防止忘記,尊重勞動(dòng)成果,轉(zhuǎn)載注明出處哦!如果你也喜歡,那...
    波波波先森閱讀 11,629評(píng)論 4 56
  • 麗娟~微信~利他組 【日精進(jìn)打卡第9天】 【知~學(xué)習(xí)】 《六項(xiàng)精進(jìn)》2遍 共16遍 《大學(xué)》2遍 共16遍 【經(jīng)典...
    李麗娟68閱讀 126評(píng)論 0 0
  • 你本來有平滑的肌膚 奈何 所有的記憶變成了歲月的紋 在你身上一點(diǎn)點(diǎn)浮現(xiàn) 我摸著你的坎坷 心都在顫抖 許久之后你會(huì)不...
    靜羽明海閱讀 208評(píng)論 0 11
  • (2017.9.4)真的沒有時(shí)間去做其他的事情了,加油親愛的,為了以后的生活,加油。3小時(shí),下午1小時(shí),晚上1小時(shí)...
    糖糖不夠甜閱讀 152評(píng)論 0 0

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