溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

什么是線程池

發(fā)布時(shí)間:2021-06-29 11:28:35 來源:億速云 閱讀:92 作者:chen 欄目:大數(shù)據(jù)

這篇文章主要講解了“什么是線程池”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“什么是線程池”吧!

1、線程池的核心類:ThreadPoolExecutor 

1.1-類圖

(I:代表接口,C:代表實(shí)現(xiàn)類)I:Executor 
    I:ExecutorService
        C:AbstractExecutorService
            C:ThreadPoolExecutor

該類的主要構(gòu)造函數(shù)如下:

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
        BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);

1.2-參數(shù)詳解:

  1. corePoolSize:核心線程池的大小。如果核心線程池有空閑位置,新的任務(wù)進(jìn)來就會被核心線程池新建一個(gè)線程執(zhí)行,執(zhí)行完畢后不會銷毀線程,線程會進(jìn)入緩存隊(duì)列等待再次被運(yùn)行。

  2. maximunPoolSize:最大的線程數(shù)量。如果核心線程池和緩存隊(duì)列都已經(jīng)滿了,新的任務(wù)進(jìn)來就會創(chuàng)建新的線程來執(zhí)行。但是數(shù)量不能超過maximunPoolSize,否側(cè)會采取拒絕接受任務(wù)策略,我們下面會具體分析。

  3. keepAliveTime:非核心線程能夠空閑的最長時(shí)間,超過時(shí)間,線程終止。這個(gè)參數(shù)默認(rèn)只有在線程數(shù)量超過核心線程池大小時(shí)才會起作用。只要線程數(shù)量不超過核心線程大小,就不會起作用。

  4. unit:時(shí)間單位,和keepAliveTime配合使用。

  5. workQueue: 緩存隊(duì)列,用來存放等待被執(zhí)行的任務(wù),有以下取值:
    1、ArrayBlockingQueue; 有界阻塞隊(duì)列,詳見文章:ArrayBlockingQueue詳解
    2、LinkedBlockingQueue; 無界阻塞隊(duì)列,詳見文章:LinkedBlockingQueue詳解
    3、SynchronousQueue; 無緩沖阻塞隊(duì)列 ,詳見文章:SynchronousQueue詳解

  6. threadFactory:線程工廠,用來創(chuàng)建線程,默認(rèn)new Executors.DefaultThreadFactory();

  7. handler: 線程拒絕策略。當(dāng)創(chuàng)建的線程超出maximumPoolSize值,且緩沖隊(duì)列已滿時(shí),對新提交任務(wù)的處理策略,有以下4種取值,我們結(jié)合代碼分析
    1、ThreadPoolExecutor.AbortPolicy 無視任務(wù)(也就是丟棄任務(wù)),并通過拋異常告知調(diào)用者“我拒絕接收新任務(wù)”

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    	//這里直接拋出異常,可理解為:無視任務(wù)(也就是丟棄任務(wù)),并通過拋異常告知調(diào)用者“我拒絕接收新任務(wù)”
    	throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString());
    }

    2、ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù),但是不做任何處理。 

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        //這里是空實(shí)現(xiàn),也就是丟棄任務(wù),不作任何的處理
        //這會導(dǎo)致:雖然此策略被觸發(fā),但調(diào)用者根本不知道它提交進(jìn)來的任務(wù),最終到底有沒有被執(zhí)行
    }

    3、ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊(duì)列最前面的任務(wù),嘗試執(zhí)行新任務(wù)。

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    	if (!e.isShutdown()) { //判斷線程池是否被關(guān)閉了
    		e.getQueue().poll();//丟棄隊(duì)列最前面的任務(wù)
    		e.execute(r); //嘗試執(zhí)行新任務(wù)
    	}
    }

    4、ThreadPoolExecutor.CallerRunsPolicy:由調(diào)用線程處理該任務(wù)

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    	if (!e.isShutdown()) { //判斷線程池是否被關(guān)閉了
    		r.run(); //調(diào)用線程直接調(diào)用run()方法,執(zhí)行其代碼邏輯
    	}
    }


     

1.3-Executors工廠類

    基于ThreadPoolExecutor 的構(gòu)造參數(shù)如此之多,JDK為我們提供了Executors類,通過它我們可以簡單的創(chuàng)建出四種類型的線程池,一般場景下夠用了。
1.3.1、固定大小線程池

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(
                  nThreads, // corePoolSize
                  nThreads,// maximumPoolSize
                  0L, TimeUnit.MILLISECONDS,// keepAliveTime=0秒
                  new LinkedBlockingQueue<Runnable>()// 利用無界阻塞隊(duì)列
               );
}

參數(shù):corePoolSize = 固定值,maximumPoolSize = 固定值,keepAliveTime = 0秒 ,workQueue =  LinkedBlockingQueue 無界阻塞隊(duì)列
分析:
1、corePoolSize 和 maximumPoolSize 都為 nThreads 一個(gè)固定值,說明此線程池中都是核心線程,keepAliveTime為核心線程空閑時(shí)間,該線程池中不存在非核心線程,所以參數(shù)keepAliveTime在此處無效
2、new LinkedBlockingQueue<Runnable>() :緩存隊(duì)列用的無界阻塞隊(duì)列,當(dāng)核心池子里的線程都在忙的時(shí)候,新進(jìn)來的任務(wù)被放到此隊(duì)列中;一旦有空閑的線程了,該線程就會從隊(duì)列里去拿任務(wù)執(zhí)行;
3、缺點(diǎn):因?yàn)橛玫氖菬o界隊(duì)列,所以當(dāng) nThreads 個(gè)線程一直被占用的情況下,同時(shí)又不斷的有新任務(wù)進(jìn)來,就有可能導(dǎo)致OOM問題;

1.3.2、單個(gè)線程的線程池

public static ExecutorService newSingleThreadExecutor() {
	return new FinalizableDelegatedExecutorService
		(new ThreadPoolExecutor(1, 1,  // corePoolSize,maximumPoolSize
								0L, TimeUnit.MILLISECONDS,// keepAliveTime=0秒
								new LinkedBlockingQueue<Runnable>())// 利用無界阻塞隊(duì)列
                             );
}

參數(shù):corePoolSize = 1,maximumPoolSize = 1,keepAliveTime = 0秒 ,workQueue =  LinkedBlockingQueue 無界阻塞隊(duì)列
分析:
1、corePoolSize 和 maximumPoolSize 都為1,此線程池只有一個(gè)核心線程,同上,參數(shù)keepAliveTime在此處無效;
2、new LinkedBlockingQueue<Runnable>() :緩存隊(duì)列用的無界阻塞隊(duì)列,當(dāng)僅有的一個(gè)核心線程在忙的時(shí)候,新進(jìn)來的任務(wù)被放到此隊(duì)列中;待線程空閑了,就會從隊(duì)列里去拿任務(wù)執(zhí)行;
3、缺點(diǎn):因?yàn)橛玫氖菬o界隊(duì)列,所以當(dāng)核心線程一直被占用的情況下,同時(shí)又不斷的有新任務(wù)進(jìn)來,就有可能導(dǎo)致OOM問題;
4、有沒有注意到,這里為什么用了一個(gè)FinalizableDelegatedExecutorService類呢?
見文章:關(guān)于newSingleThreadExecutor中的FinalizableDelegatedExecutorService源碼分析

1.3.3、緩存線程池

public static ExecutorService newCachedThreadPool() {
	return new ThreadPoolExecutor(0, Integer.MAX_VALUE,// corePoolSize,maximumPoolSize
								  60L, TimeUnit.SECONDS,// keepAliveTime=60秒
								  new SynchronousQueue<Runnable>());// 同步阻塞隊(duì)列
}

參數(shù):corePoolSize = 0,maximumPoolSize = 無限大,keepAliveTime = 60秒(重要) ,workQueue =  SynchronousQueue 無緩沖阻塞隊(duì)列
分析:一個(gè)可以根據(jù)需要?jiǎng)?chuàng)建線程的線程池,此線程池中所有線程都為非核心線程,且最大空閑時(shí)間為60秒,最多可以創(chuàng)建Integer.MAX_VALUE 個(gè)線程(2^31次方,21億多,可以視為無限);SynchronousQueue 為無緩沖阻塞隊(duì)列,也就是此隊(duì)列里不會緩沖新的任務(wù),有新任務(wù)進(jìn)來時(shí),如果無空閑線程,就會新創(chuàng)建一個(gè)線程;如果有空閑線程,就會使用空閑線程;所以此線程池適合執(zhí)行一些執(zhí)行周期短的任務(wù)。

感謝各位的閱讀,以上就是“什么是線程池”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對什么是線程池這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI