優(yōu)雅的創(chuàng)建線程池

手動(dòng)創(chuàng)建線程

平時(shí)開發(fā)中經(jīng)常會(huì)碰到需要用異步方式來(lái)實(shí)現(xiàn)某個(gè)需求幅虑,這時(shí)首先會(huì)想到這種寫法

new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("to do something");
    }
}).start(); 

或者用lambda簡(jiǎn)寫

new Thread(()-> System.out.println("to do something")).start();

雖然這種寫法可以實(shí)現(xiàn)需求,但是我們最好不要這樣寫同规,因?yàn)檫@種是不可控的盯孙。復(fù)雜的系統(tǒng)里,如果有很多這種寫法宫患,就會(huì)導(dǎo)致明明可以幾個(gè)線程就能完成的任務(wù),最后創(chuàng)建了幾十個(gè)線程这弧,導(dǎo)致線程過(guò)度切換娃闲,降低系統(tǒng)性能。

因此當(dāng)我們需要異步處理的時(shí)候匾浪,應(yīng)該使用線程池皇帮。

線程池

第一種 使用Executors創(chuàng)建

Executors提供了四種創(chuàng)建線程池的方法

  • newSingleThreadExecutor 創(chuàng)建只有一個(gè)線程的線程池,這個(gè)線程池可以在線程死后(或發(fā)生異常時(shí))重新啟動(dòng)一個(gè)線程來(lái)替代原來(lái)的線程繼續(xù)執(zhí)行下去蛋辈!
public static void main(String[] args) {
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    executorService.execute(new Worker());
    executorService.execute(new Worker());
    executorService.shutdown();
}
static class Worker implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+":working");
    }
}

結(jié)果
pool-1-thread-1:working
pool-1-thread-1:working
  • newCachedThreadPool 創(chuàng)建一個(gè)可緩存線程池
  • newFixedThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池
  • newScheduledThreadPool 創(chuàng)建一個(gè)線程池属拾,它可安排在給定延遲后運(yùn)行命令或者定期地執(zhí)行。

不推薦使用Executors創(chuàng)建線程池

其實(shí)通過(guò)Executors創(chuàng)建的四種線程池方法冷溶,底層都是通過(guò)創(chuàng)建ThreadPoolExecutor來(lái)實(shí)現(xiàn)的渐白,這四種方法只是為我們封裝了創(chuàng)建的細(xì)節(jié)。但是我們平時(shí)開發(fā)中最好要知道逞频,核心線程數(shù)多少纯衍,緩存隊(duì)列大小等等這些重要的參數(shù),這樣以后出現(xiàn)bug不至于無(wú)從下手苗胀。

第二種 使用ThreadPoolExecutor創(chuàng)建

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;
}
  • corePoolSize 核心線程數(shù)
  • maximumPoolSize 最大線程數(shù)
  • keepAliveTime 當(dāng)線程數(shù)大于核心線程數(shù)時(shí)襟诸,空余線程等待新任務(wù)的最長(zhǎng)時(shí)間
  • unit 時(shí)間單位
  • workQueue 等待隊(duì)列
  • threadFactory 線程工廠
  • handler 當(dāng)線程大于最大線程數(shù)時(shí)采用的拒絕策略

各個(gè)參數(shù)如下圖所示

threadPool

我們?cè)趧?chuàng)建的時(shí)候也可以采用ThreadPoolExecutor缺省的構(gòu)造方法瓦堵,其中一些參數(shù)使用默認(rèn)即可。

public static void main(String[] args) {
    ThreadFactory threadFactory = new ThreadNameFactory();
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10),threadFactory);
    threadPoolExecutor.execute(new Worker());
    threadPoolExecutor.execute(new Worker());
    threadPoolExecutor.shutdown();
}
static class ThreadNameFactory implements ThreadFactory {
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    @Override
    public Thread newThread(Runnable r) {
        return new Thread(r, threadNumber.getAndIncrement()+"號(hào)員工");
    }
}
static class Worker implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+":working");
    }
}

結(jié)果
1號(hào)員工:working
2號(hào)員工:working

上面例子中我們?cè)O(shè)置了核心線程數(shù)是5歌亲,最大線程數(shù)是10菇用,等待時(shí)間是5s,等待隊(duì)列采用的是ArrayBlockingQueue应结,線程工廠使用自定義的刨疼,只是自定義了線程名稱。

總結(jié)

平時(shí)開發(fā)中鹅龄,不論什么時(shí)候都最好不要手動(dòng)創(chuàng)建線程執(zhí)行異步任務(wù),應(yīng)該使用線程池來(lái)處理亭畜,有利于線程可控和復(fù)用扮休,提升系統(tǒng)性能,線程池采用ThreadPoolExecutor創(chuàng)建拴鸵。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末玷坠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子劲藐,更是在濱河造成了極大的恐慌八堡,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件聘芜,死亡現(xiàn)場(chǎng)離奇詭異兄渺,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)汰现,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門挂谍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人瞎饲,你說(shuō)我怎么就攤上這事口叙。” “怎么了嗅战?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵妄田,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我驮捍,道長(zhǎng)疟呐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任厌漂,我火速辦了婚禮萨醒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘苇倡。我一直安慰自己富纸,他們只是感情好囤踩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著晓褪,像睡著了一般堵漱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上涣仿,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天勤庐,我揣著相機(jī)與錄音,去河邊找鬼好港。 笑死愉镰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的钧汹。 我是一名探鬼主播丈探,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼拔莱!你這毒婦竟也來(lái)了碗降?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤塘秦,失蹤者是張志新(化名)和其女友劉穎讼渊,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尊剔,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡爪幻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赋兵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笔咽。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖霹期,靈堂內(nèi)的尸體忽然破棺而出叶组,到底是詐尸還是另有隱情,我是刑警寧澤历造,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布甩十,位于F島的核電站,受9級(jí)特大地震影響吭产,放射性物質(zhì)發(fā)生泄漏侣监。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一臣淤、第九天 我趴在偏房一處隱蔽的房頂上張望橄霉。 院中可真熱鬧,春花似錦邑蒋、人聲如沸姓蜂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)钱慢。三九已至逮京,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間束莫,已是汗流浹背懒棉。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留览绿,地道東北人策严。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像饿敲,于是被迫代替她去往敵國(guó)和親享钞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容