java四種線程池配置詳解

參考:https://www.cnblogs.com/dolphin0520/p/3932921.html

做下總結:

java線程池的主要類是ThreadPoolExecutor

在這裏插入圖片描述

此類是java線程池的核心類,後面介紹的四種線程池基本是此類的不同構造
先來看下它的構造方法:
在這裏插入圖片描述

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

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

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

實際上前三種構造方法都是第四種的參數簡化重載,主要是配置類一些的成員變量

下面解釋下一下構造器中各個參數的含義:

corePoolSize

核心池的大小,這個參數跟後面講述的線程池的實現原理有非常大的關係。在創建了線程池後,默認情況下,線程池中並沒有任何線程,而是等待有任務到來才創建線程去執行任務,除非調用了prestartAllCoreThreads()或者prestartCoreThread()方法,從這2個方法的名字就可以看出,是預創建線程的意思,即在沒有任務到來之前就創建corePoolSize個線程或者一個線程。默認情況下,在創建了線程池後,線程池中的線程數爲0,當有任務來之後,就會創建一個線程去執行任務,當線程池中的線程數目達到corePoolSize後,就會把到達的任務放到緩存隊列當中;

maximumPoolSize

線程池最大線程數,這個參數也是一個非常重要的參數,它表示在線程池中最多能創建多少個線程;

keepAliveTime

表示線程沒有任務執行時最多保持多久時間會終止。默認情況下,只有當線程池中的線程數大於corePoolSize時,keepAliveTime纔會起作用,直到線程池中的線程數不大於corePoolSize,即當線程池中的線程數大於corePoolSize時,如果一個線程空閒的時間達到keepAliveTime,則會終止,直到線程池中的線程數不超過corePoolSize。但是如果調用了allowCoreThreadTimeOut(boolean)方法,在線程池中的線程數不大於corePoolSize時,keepAliveTime參數也會起作用,直到線程池中的線程數爲0;

unit

參數keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態屬性:

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

workQueue

一個阻塞隊列,用來存儲等待執行的任務,這個參數的選擇也很重要,會對線程池的運行過程產生重大影響,一般來說,這裏的阻塞隊列有以下幾種選擇:
1)ArrayBlockingQueue:基於數組的先進先出隊列,此隊列創建時必須指定大小;
2)LinkedBlockingQueue:基於鏈表的先進先出隊列,如果創建時沒有指定此隊列大小,則默認爲Integer.MAX_VALUE;
3)synchronousQueue:這個隊列比較特殊,它不會保存提交的任務,而是將直接新建一個線程來執行新來的任務。
4)DelayedWorkQueue:

ArrayBlockingQueue使用較少,一般使用LinkedBlockingQueue和Synchronous。線程池的排隊策略與BlockingQueue有關。

threadFactory

線程工廠,默認是DefaultThreadFactory,主要用來創建線程;

handler

:表示當拒絕處理任務時的策略,有以下四種取值(默認是AbortPolicy):
ThreadPoolExecutor.AbortPolicy:丟棄任務並拋出RejectedExecutionException異常。
ThreadPoolExecutor.DiscardPolicy:也是丟棄任務,但是不拋出異常。
ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然後重新嘗試執行任務(重複此過程)
ThreadPoolExecutor.CallerRunsPolicy:由調用線程處理該任務

基本要配置的也就是corePoolSize,maximumPoolSize,unit,keepAliveTime,workQueue這五個參數,也就是使用第一種構造函數就可以了,後面兩個參數一般選擇默認就可以;

然而,java doc甚至第一種構造函數也不希望你直接手動配置使用,所以便有了以下四種java線程池,這四種線程池就是官方給你定製好參數的ThreadPoolExecutor,基本是使用上述的第一種構造函數,也就是給你配置好corePoolSize,maximumPoolSize,unit,keepAliveTime,workQueue這幾個參數。

四種線程池:

newCachedThreadPool

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

將corePoolSize設置爲0,將maximumPoolSize設置爲Integer.MAX_VALUE,相當於一個超大的線程池,使用的SynchronousQueue,
也就是說來了任務就創建線程運行,當線程空閒超過60秒,就銷燬線程,是一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。

newFixedThreadPool

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

創建的線程池corePoolSize和maximumPoolSize值是相等的,就是傳入的整型參數,它使用的LinkedBlockingQueue,隊列使用默認大小Integer.MAX_VALUE。這是一個定長線程池,可控制線程最大併發數,當線程數達到corePoolSize(maximumPoolSize),不會有新的線程建立,新加入的線程會加入到隊列(直到數量達到Integer.MAX_VALUE纔會採取拒絕措施),等待空閒的線程處理。

newScheduledThreadPool

public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

corePoolSize爲傳入的參數,maximumPoolSize是Integer.MAX_VALUE,
創建一個定長線程池,支持定時及週期性任務執行。

newSingleThreadExecutor

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

將corePoolSize和maximumPoolSize都設置爲1,也使用的LinkedBlockingQueue,隊列使用默認大小Integer.MAX_VALUE;
是一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。

線程進入到線程池的基本執行思想是:

•如果當前線程池中的線程數目小於corePoolSize,則每來一個任務,就會創建一個線程去執行這個任務;

•如果當前線程池中的線程數目>=corePoolSize,則每來一個任務,會嘗試將其添加到任務緩存隊列當中,若添加成功,則該任務會等待空閒線程將其取出去執行;若添加失敗(一般來說是任務緩存隊列已滿),則會嘗試創建新的線程但不會多於maximumPoolSize去執行這個任務;

•如果當前線程池中的線程數目達到maximumPoolSize,則會採取任務拒絕策略進行處理;

•如果線程池中的線程數量大於 corePoolSize時,如果某線程空閒時間超過keepAliveTime,線程將被銷燬,直至線程池中的線程數目不大於corePoolSize;如果允許爲核心池中的線程設置存活時間,也就是調用了allowCoreThreadTimeOut(boolean)方法,那麼核心池中的線程空閒時間超過keepAliveTime,線程也會被銷燬,直至爲0。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章