成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

關(guān)于線程池你不得不知道的一些設(shè)置

余學(xué)文 / 1596人閱讀

摘要:有細(xì)心的網(wǎng)友早就想到了這個(gè)問(wèn)題在線程池中,還有一些不常用的設(shè)置。所以該方法會(huì)在線程池總預(yù)先創(chuàng)建沒(méi)有任務(wù)執(zhí)行的線程,數(shù)量為。下面我們測(cè)試一下從測(cè)試結(jié)果來(lái)看,線程池中已經(jīng)預(yù)先創(chuàng)建了數(shù)量的空閑線程。

微信公眾號(hào)「后端進(jìn)階」,專注后端技術(shù)分享:Java、Golang、WEB框架、分布式中間件、服務(wù)治理等等。  
老司機(jī)傾囊相授,帶你一路進(jìn)階,來(lái)不及解釋了快上車!

看完我上一篇文章「你都理解創(chuàng)建線程池的參數(shù)嗎?」之后,當(dāng)遇到這種問(wèn)題,你覺(jué)得你完全能夠唬住面試官了,50k輕松到手。殊不知,要是面試官此刻給你來(lái)個(gè)反殺:

初始化線程池時(shí)可以預(yù)先創(chuàng)建線程嗎?線程池的核心線程可以被回收嗎?為什么?

如果此刻你一臉懵逼,這個(gè)要慌,問(wèn)題很大,50k馬上變5k。

有細(xì)心的網(wǎng)友早就想到了這個(gè)問(wèn)題:

在ThreadPoolExecutor線程池中,還有一些不常用的設(shè)置。我建議如果您在應(yīng)用場(chǎng)景中沒(méi)有特殊的要求,就不需要使用這些設(shè)置。

初始化線程池時(shí)可以預(yù)先創(chuàng)建線程嗎? prestartAllCoreThreads

初始化線程池時(shí)是可以預(yù)先創(chuàng)建線程的,初始化線程池后,再調(diào)用prestartAllCoreThreads()方法,即可預(yù)先創(chuàng)建corePoolSize數(shù)量的核心線程,我們看源碼:

public int prestartAllCoreThreads() {
    int n = 0;
    while (addWorker(null, true))
        ++n;
    return n;
}
private boolean addWorker(Runnable firstTask, boolean core) {
  // ..
}

addWorker方法目的是在線程池中添加任務(wù)并執(zhí)行,如果task為空,線程獲取任務(wù)執(zhí)行時(shí)調(diào)用getTask()方法,該方法從blockingQueue阻塞隊(duì)列中阻塞獲取任務(wù)執(zhí)行,因此線程不會(huì)釋放,留存在線程池中,如果core=true,說(shuō)明任務(wù)只能利用核心線程來(lái)執(zhí)行。

所以該方法會(huì)在線程池總預(yù)先創(chuàng)建沒(méi)有任務(wù)執(zhí)行的線程,數(shù)量為corePoolSize。

下面我們測(cè)試一下:

從測(cè)試結(jié)果來(lái)看,線程池中已經(jīng)預(yù)先創(chuàng)建了corePoolSize數(shù)量的空閑線程。

prestartCoreThread

prestartCoreThread()同樣可以預(yù)先創(chuàng)建線程,只不過(guò)該方法只會(huì)與創(chuàng)建1條線程,我們來(lái)看源碼:

public boolean prestartCoreThread() {
    return workerCountOf(ctl.get()) < corePoolSize &&
        addWorker(null, true);
}

從方法源碼可知,如果此時(shí)工作線程數(shù)量小于corePoolSize,那么就調(diào)用addWorker創(chuàng)建1條空閑核心線程。

下面我們測(cè)試一下:

從測(cè)試結(jié)果來(lái)看,線程池中已經(jīng)預(yù)先創(chuàng)建了1條空閑線程。

線程池的核心線程可以被回收嗎?

你可能會(huì)想到將corePoolSize的數(shù)量設(shè)置為0,從而線程池的所有線程都是“臨時(shí)”的,只有keepAliveTime存活時(shí)間,你的思路也許時(shí)正確的,但你有沒(méi)有想過(guò)一個(gè)很嚴(yán)重的后果,corePoolSize=0時(shí),任務(wù)需要填滿阻塞隊(duì)列才會(huì)創(chuàng)建線程來(lái)執(zhí)行任務(wù),阻塞隊(duì)列有設(shè)置長(zhǎng)度還好,如果隊(duì)列長(zhǎng)度無(wú)限大呢,你就等著OOM異常吧,所以用這種設(shè)置行為并不是我們所需要的。

有沒(méi)有什么設(shè)置可以回收核心線程呢?

allowCoreThreadTimeOut

ThreadPoolExecutor有一個(gè)私有成員變量:

private volatile boolean allowCoreThreadTimeOut;

如果allowCoreThreadTimeOut=true,核心線程在規(guī)定時(shí)間內(nèi)會(huì)被回收。

上面我也說(shuō)了,當(dāng)線程空閑時(shí)會(huì)從blockingQueue阻塞隊(duì)列中阻塞獲取任務(wù)執(zhí)行,所以我們來(lái)看看是保證核心線程不被銷毀的,我們直接定位到源碼部位:

java.util.concurrent.ThreadPoolExecutor#getTask:

boolean timedOut = false; // Did the last poll() time out?
for (;;) {
    // Are workers subject to culling?
    boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

    try {
        Runnable r = timed ?
            workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
        workQueue.take();
        if (r != null)
            return r;
        timedOut = true;
    } catch (InterruptedException retry) {
        timedOut = false;
    }
}

這里的關(guān)鍵值timed,如果allowCoreThreadTimeOut=true或者此時(shí)工作線程大于corePoolSize,timed=true,如果timed=true,會(huì)調(diào)用poll()方法從阻塞隊(duì)列中獲取任務(wù),否則調(diào)用take()方法獲取任務(wù)。

下面我來(lái)解釋這兩個(gè)方法:

poll(long timeout, TimeUnit unit):從BlockingQueue取出一個(gè)任務(wù),如果不能立即取出,則可以等待timeout參數(shù)的時(shí)間,如果超過(guò)這個(gè)時(shí)間還不能取出任務(wù),則返回null;

take():從blocking阻塞隊(duì)列取出一個(gè)任務(wù),如果BlockingQueue為空,阻斷進(jìn)入等待狀態(tài)直到BlockingQueue有新的任務(wù)被加入為止。

到這里,我們就很好地解釋了,當(dāng)allowCoreThreadTimeOut=true或者此時(shí)工作線程大于corePoolSize時(shí),線程調(diào)用BlockingQueue的poll方法獲取任務(wù),若超過(guò)keepAliveTime時(shí)間,則返回null,timedOut=true,則getTask會(huì)返回null,線程中的runWorker方法會(huì)退出while循環(huán),線程接下來(lái)會(huì)被回收。

下面我們測(cè)試一下:

可以看到,核心線程被回收了。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77615.html

相關(guān)文章

  • 線程池你真不來(lái)了解一下嗎?

    摘要:所以說(shuō)我們的線程最好是交由線程池來(lái)管理,這樣可以減少對(duì)線程生命周期的管理,一定程度上提高性能。線程池不接收新任務(wù),不處理已添加的任務(wù),并且會(huì)中斷正在處理的任務(wù)。當(dāng)所有的任務(wù)已終止,記錄的任務(wù)數(shù)量為,線程池會(huì)變?yōu)闋顟B(tài)。線程池徹底終止的狀態(tài)。 前言 只有光頭才能變強(qiáng) 回顧前面: ThreadLocal就是這么簡(jiǎn)單 多線程三分鐘就可以入個(gè)門了! 多線程基礎(chǔ)必要知識(shí)點(diǎn)!看了學(xué)習(xí)多線程事半功倍...

    stdying 評(píng)論0 收藏0
  • 線程之死鎖就是這么簡(jiǎn)單

    摘要:此時(shí)線程需要鎖才能繼續(xù)往下執(zhí)行。但是線程的鎖并沒(méi)有釋放,線程的鎖也沒(méi)有釋放。 前言 只有光頭才能變強(qiáng) 回顧前面: ThreadLocal就是這么簡(jiǎn)單 多線程三分鐘就可以入個(gè)門了! 多線程基礎(chǔ)必要知識(shí)點(diǎn)!看了學(xué)習(xí)多線程事半功倍 Java鎖機(jī)制了解一下 AQS簡(jiǎn)簡(jiǎn)單單過(guò)一遍 Lock鎖子類了解一下 線程池你真不來(lái)了解一下嗎? 本篇主要是講解死鎖,這是我在多線程的最后一篇了。主要將多線程...

    winterdawn 評(píng)論0 收藏0
  • 【Java】幾道讓你拿offer面試題

    摘要:的方法,的默認(rèn)實(shí)現(xiàn)會(huì)判斷是否是類型注意自動(dòng)拆箱,自動(dòng)裝箱問(wèn)題。適應(yīng)自旋鎖鎖競(jìng)爭(zhēng)是下的,會(huì)經(jīng)過(guò)用戶態(tài)到內(nèi)核態(tài)的切換,是比較花時(shí)間的。在中引入了自適應(yīng)的自旋鎖,說(shuō)明自旋的時(shí)間不固定,要不要自旋變得越來(lái)越聰明。 前言 只有光頭才能變強(qiáng) 之前在刷博客的時(shí)候,發(fā)現(xiàn)一些寫得比較好的博客都會(huì)默默收藏起來(lái)。最近在查閱補(bǔ)漏,有的知識(shí)點(diǎn)比較重要的,但是在之前的博客中還沒(méi)有寫到,于是趁著閑整理一下。 文本的...

    張春雷 評(píng)論0 收藏0
  • 關(guān)于偏向鎖,安全點(diǎn),JIT一些暗坑.

    摘要:前言本文是一篇簡(jiǎn)短的雜糅本文源自于作者最近的一個(gè)疑問(wèn)為什么在舊版的中偏向鎖的移除一定要在全局安全點(diǎn)進(jìn)行同時(shí)在上個(gè)星期作者參與的一個(gè)項(xiàng)目發(fā)生了一件怪事一個(gè)服務(wù)莫名其妙地不接受任何請(qǐng)求了一切請(qǐng)求都是而查看日志發(fā)現(xiàn)出故障的服務(wù)本身去請(qǐng)求另一個(gè)服務(wù) 前言 本文是一篇簡(jiǎn)短的雜糅. 本文源自于作者最近的一個(gè)疑問(wèn):為什么在舊版的jdk中偏向鎖的移除一定要在全局安全點(diǎn)進(jìn)行?同時(shí)在上個(gè)星期,作者參與的一...

    JeOam 評(píng)論0 收藏0
  • 給女朋友講解什么是代理模式

    摘要:受知乎文章和設(shè)計(jì)模式之禪的啟發(fā),我也來(lái)搞一篇腦洞小開的文章由標(biāo)題可知,這篇文章是寫給我女朋友看的。于是這就讓經(jīng)紀(jì)人對(duì)粉絲說(shuō)只有萬(wàn),我才會(huì)寫代碼。 前言 只有光頭才能變強(qiáng) 回顧前面: ThreadLocal就是這么簡(jiǎn)單 多線程三分鐘就可以入個(gè)門了! 多線程基礎(chǔ)必要知識(shí)點(diǎn)!看了學(xué)習(xí)多線程事半功倍 Java鎖機(jī)制了解一下 AQS簡(jiǎn)簡(jiǎn)單單過(guò)一遍 Lock鎖子類了解一下 線程池你真不來(lái)了解一下...

    stormgens 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<