Java線程池

一、什么是線程池渊鞋?

線程的創(chuàng)建和銷毀對(duì)于系統(tǒng)來(lái)說(shuō)是一種較大的開(kāi)銷胀莹,線程池通過(guò)多個(gè)任務(wù)重用線程基跑,線程創(chuàng)建的開(kāi)銷就被分?jǐn)偟搅硕鄠€(gè)任務(wù)上,而且請(qǐng)求到達(dá)時(shí)線程已經(jīng)存在描焰,消除了等待線程創(chuàng)建帶來(lái)的延遲媳否,使得程序響應(yīng)更快。

二荆秦、線程池的優(yōu)點(diǎn)是什么篱竭?

線程池主要用來(lái)解決線程生命周期開(kāi)銷問(wèn)題和資源不足問(wèn)題。如果每當(dāng)一個(gè)請(qǐng)求到達(dá)就創(chuàng)建一個(gè)新線程步绸,開(kāi)銷是挺大的掺逼,甚至在創(chuàng)建和銷毀線程上花費(fèi)的時(shí)間和消耗的資源要大于處理用戶請(qǐng)求的時(shí)間和資源。另外如果創(chuàng)建線程太多瓤介,系統(tǒng)會(huì)由于過(guò)度消耗內(nèi)存和切換過(guò)度頻繁導(dǎo)致系統(tǒng)資源不足吕喘。因而可以通過(guò)線程池盡可能減少創(chuàng)建和銷毀線程的次數(shù),利用已有的對(duì)象進(jìn)行服務(wù)刑桑。

三氯质、線程池實(shí)現(xiàn)類

JDK中提供了java.util.concurrent.ThreadPoolExecutor類來(lái)實(shí)現(xiàn)線程池,其構(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.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

我們先對(duì)構(gòu)造方法中的參數(shù)進(jìn)行介紹:

1祠斧、int corePoolSize

核心池的大小闻察,默認(rèn)情況下創(chuàng)建線程池之后線程池沒(méi)有線程,而是等待任務(wù)到來(lái)才創(chuàng)建線程去執(zhí)行任務(wù)琢锋,除非是調(diào)用了prestartAllCoreThreads()方法辕漂,進(jìn)行線程的預(yù)創(chuàng)建,創(chuàng)建corePoolSize個(gè)線程吴超。

public int prestartAllCoreThreads() {
        int n = 0;
        while (addWorker(null, true))
            ++n;
        return n;
    }

2钮热、int maximumPoolSize

線程池最大線程個(gè)數(shù),表示線程池中最多能創(chuàng)建的線程個(gè)數(shù)

3烛芬、long keepAliveTime

表示線程多久沒(méi)有任務(wù)執(zhí)行就會(huì)被銷毀
默認(rèn)情況下隧期,當(dāng)線程數(shù)量大于corePoolSize時(shí)飒责,keepAliveTime才會(huì)生效,銷毀線程池中線程直到線程數(shù)量不大于corePoolSize仆潮;
但是如果調(diào)用了allowCoreThreadTimeOut(boolean)方法宏蛉,傳入?yún)?shù)為true時(shí),如注釋所說(shuō):核心線程也會(huì)被銷毀性置,直到線程數(shù)量為0拾并。

/**
     * If false (default), core threads stay alive even when idle.
     * If true, core threads use keepAliveTime to time out waiting
     * for work.
     *如果為false(默認(rèn)值),則即使處于空閑狀態(tài)鹏浅,核心線程也保持活動(dòng) 
     *狀態(tài)嗅义。如果為true,則核心線程使用keepAliveTime來(lái)超時(shí)等待工作隐砸。
     */
private volatile boolean allowCoreThreadTimeOut;

public void allowCoreThreadTimeOut(boolean value) {
        if (value && keepAliveTime <= 0)
            throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
        if (value != allowCoreThreadTimeOut) {
            allowCoreThreadTimeOut = value;
            if (value)
                //銷毀空閑線程
                interruptIdleWorkers();
        }
    }

4之碗、TimeUnit unit

上一個(gè)參數(shù)keepAliveTime的時(shí)間單位,有7種靜態(tài)屬性取值:

        TimeUnit.DAYS;          //天
        TimeUnit.HOURS;         //小時(shí)
        TimeUnit.MINUTES;       //分鐘
        TimeUnit.SECONDS;       //秒
        TimeUnit.MILLISECONDS;  //毫秒
        TimeUnit.MICROSECONDS;  //微秒
        TimeUnit.NANOSECONDS;   //納秒

5季希、BlockingQueue<Runnable> workQueue

阻塞隊(duì)列褪那,用來(lái)存儲(chǔ)等待執(zhí)行的任務(wù),有以下三種:
SynchronousQueue(默認(rèn))直接提交策略式塌;
LinkedBlockingQueue無(wú)界隊(duì)列策略博敬;
ArrayBlockingQueue有界隊(duì)列策略。

(1)峰尝、SynchronousQueue(默認(rèn))直接提交策略

工作隊(duì)列不保存任何的任務(wù)等待執(zhí)行偏窝,而是直接提交給線程進(jìn)行執(zhí)行;如果沒(méi)有可用于立即執(zhí)行任務(wù)的線程武学,則會(huì)創(chuàng)建一個(gè)新的線程來(lái)執(zhí)行祭往。此策略下maximumPoolSize將會(huì)失效。

(2)劳淆、LinkedBlockingQueue無(wú)界隊(duì)列策略

無(wú)界指的是工作隊(duì)列大小,可以指定大小默赂,如果不指定沛鸵,默認(rèn)為Integer.MAX_VALUE,如果添加速度大于刪除速度的時(shí)候缆八,有可能會(huì)內(nèi)存溢出曲掰。

(3)、ArrayBlockingQueue有界隊(duì)列策略

有界也就意味著奈辰,它的大小是有限制的栏妖。所以在創(chuàng)建 ArrayBlockingQueue 時(shí),必須要給它指定一個(gè)隊(duì)列的大薪鼻 吊趾;可以防止資源耗盡的情況發(fā)生宛裕。

6、ThreadFactory threadFactory

線程工廠论泛,用來(lái)創(chuàng)建線程的工廠類

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().
        setNameFormat("demo-pool-%d").build();

7揩尸、RejectedExecutionHandler handler

線程池拒絕策略,當(dāng)線程池的任務(wù)緩存隊(duì)列已滿并且線程池中的線程數(shù)目達(dá)到maximumPoolSize屁奏,如果還有任務(wù)到來(lái)就會(huì)采取任務(wù)拒絕策略岩榆,有以下幾種:
(1)、AbortPolicy
java線程池默認(rèn)的阻塞策略坟瓢,即不執(zhí)行此新任務(wù)勇边,而且直接拋出一個(gè)運(yùn)行時(shí)異常(RejectedExecutionException

//丟棄任務(wù)并拋出RejectedExecutionException異常。
public static class AbortPolicy implements RejectedExecutionHandler {  
    public AbortPolicy() { }  
    // 拋出異常  
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {  
        throw new RejectedExecutionException("Task " + r.toString() +  " rejected from " +  e.toString());  
    }  
}  

(2)折联、DiscardPolicy
直接丟棄任務(wù)粒褒,不執(zhí)行,但是不拋出異常

public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardPolicy}.
         */
        public DiscardPolicy() { }

        /**
         * Does nothing, which has the effect of discarding task r.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }

(3)崭庸、DiscardOldestPolicy
當(dāng)有任務(wù)添加到線程池被拒絕時(shí)怀浆,線程池會(huì)丟棄阻塞隊(duì)列中位于頭部的任務(wù),將被拒絕的任務(wù)添加到末尾怕享,然后重試執(zhí)行程序执赡,如果再次失敗,則重復(fù)此過(guò)程

public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
         */
        public DiscardOldestPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }

(4)函筋、CallerRunsPolicy
由調(diào)用線程來(lái)執(zhí)行被拒絕的任務(wù)沙合,如果執(zhí)行程序已關(guān)閉,則會(huì)丟棄該任務(wù)

public static class CallerRunsPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code CallerRunsPolicy}.
         */
        public CallerRunsPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末跌帐,一起剝皮案震驚了整個(gè)濱河市首懈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谨敛,老刑警劉巖究履,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異脸狸,居然都是意外死亡最仑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門炊甲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)泥彤,“玉大人,你說(shuō)我怎么就攤上這事卿啡∫髁撸” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵颈娜,是天一觀的道長(zhǎng)剑逃。 經(jīng)常有香客問(wèn)我浙宜,道長(zhǎng),這世上最難降的妖魔是什么炕贵? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任梆奈,我火速辦了婚禮,結(jié)果婚禮上称开,老公的妹妹穿的比我還像新娘亩钟。我一直安慰自己,他們只是感情好鳖轰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布清酥。 她就那樣靜靜地躺著,像睡著了一般蕴侣。 火紅的嫁衣襯著肌膚如雪焰轻。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天昆雀,我揣著相機(jī)與錄音辱志,去河邊找鬼。 笑死狞膘,一個(gè)胖子當(dāng)著我的面吹牛揩懒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播挽封,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼已球,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了辅愿?” 一聲冷哼從身側(cè)響起智亮,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎点待,沒(méi)想到半個(gè)月后阔蛉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡癞埠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年状原,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片燕差。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡遭笋,死狀恐怖坝冕,靈堂內(nèi)的尸體忽然破棺而出徒探,到底是詐尸還是另有隱情,我是刑警寧澤喂窟,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布测暗,位于F島的核電站央串,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏碗啄。R本人自食惡果不足惜质和,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望稚字。 院中可真熱鬧饲宿,春花似錦、人聲如沸胆描。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)昌讲。三九已至国夜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間短绸,已是汗流浹背车吹。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工醋闭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窄驹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓目尖,卻偏偏與公主長(zhǎng)得像馒吴,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瑟曲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354