java中四种线程池及poolSize、corePoolSize、maximumPoolSize
目錄
ThreadPoolExecutor重要參數
poolSize、corePoolSize、maximumPoolSize
四種線程池
newFixedThreadPool
newCachedThreadPool
newSingleThreadExecutor
newScheduledThreadPool
阻塞隊列
ThreadPoolExecutor重要參數
ThreadPoolExecutor有幾個重要的成員變量:keepAliveTime、allowCoreThreadTimeOut、poolSize、corePoolSize、maximumPoolSize。下面分別介紹一下:
-
corePoolSize:線程池的基本大小。下面會解釋什么是基本大小。
-
maximumPoolSize:線程池中允許的最大線程數。
注意還有一個largestPoolSize,記錄了曾經出現的最大線程個數。因為setMaximumPoolSize()可以改變最大線程數。
-
poolSize:線程池中當前線程的數量。
-
allowCoreThreadTimeOut:是否允許核心線程超時退出。
如果該值為false,且poolSize<=corePoolSize,線程池都會保證這些核心線程處于存活狀態,不會超時退出。
如果為true,則不論poolSize的大小,都允許超時退出。
如果poolSize>corePoolSize,則該參數不論true還是false,都允許超時退出。
相關判斷如下:
(poolSize > corePoolSize || allowCoreThreadTimeOut) 復制代碼 -
keepAliveTime: 如果一個線程處在空閑狀態的時間超過了該屬性值,就會因為超時而退出。是否允許超時退出則取決于上面的邏輯。
poolSize、corePoolSize、maximumPoolSize
那么poolSize、corePoolSize、maximumPoolSize三者的關系是如何的呢?
當新提交一個任務時:
所以通過上面的描述可知corePoolSize<=maximumPoolSize,poolSize<=maximumPoolSize;而poolSize和corePoolSize無法比較,poolSize是有可能比corePoolSize大的。
四種線程池
Executors提供四種線程池:
- newCachedThreadPool :緩存線程池,如果線程池長度超過處理需要,可回收空閑線程,若無可回收,則新建線程。
- newFixedThreadPool : 定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。
- newScheduledThreadPool : 計劃線程池,支持定時及周期性任務執行。
- newSingleThreadExecutor :單線程線程池,用唯一的線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
那么corePoolSize、maximumPoolSize在上面四種線程池中如何設定的?
通過幾個newXXX函數的源碼就可以知道,源碼如下:
newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()); } 復制代碼定長線程池的corePoolSize、maximumPoolSize相同。都是設定值。
newCachedThreadPool
public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>()); } 復制代碼緩存線程池corePoolSize為0,maximumPoolSize則是int最大值。
newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>())); } 復制代碼單線程線程池corePoolSize和maximumPoolSize都是1。
newScheduledThreadPool
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE,DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,new DelayedWorkQueue()); } 復制代碼計劃線程池用的是ThreadPoolExecutor的一個子類,可以看到corePoolSize是定義的,而maximumPoolSize則是int最大值。
注意這里的corePoolSize、maximumPoolSize不是最終的,因為可以通過setCorePoolSize和setMaximumPoolSize()改變。
阻塞隊列
上面提到阻塞隊列的飽和,那么這個飽和值是多少呢?
通過上面的代碼可以看到
(1) 定長線程池和單線程線程都使用LinkedBlockingQueue,而LinkedBlockingQueue默認的大小是int的最大值,如下:
public LinkedBlockingQueue() {this(Integer.MAX_VALUE); } 復制代碼(2)計劃線程池使用的是DelayedWordQueue,它默認大小是16,但是可以動態增長,最大值則是int的最大值,如下:
private static final int INITIAL_CAPACITY = 16; private RunnableScheduledFuture<?>[] queue =new RunnableScheduledFuture<?>[INITIAL_CAPACITY]; private void grow() {int oldCapacity = queue.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // grow 50%if (newCapacity < 0) // overflownewCapacity = Integer.MAX_VALUE;queue = Arrays.copyOf(queue, newCapacity); } 復制代碼(3)緩存線程池使用的則是SynchronousQueue,這個比較特殊沒有所謂的飽和值,而且前面也看到了緩存線程池的corePoolSize默認是0。所以它新建一個線程與 SynchronousQueue的機制有關, 這里不展開說了,有興趣的可以研究一下這個類。
關注公眾號:BennuCTech,發送“Java并發編程實戰”獲取經典書籍《Java并發編程實戰》電子版!
總結
以上是生活随笔為你收集整理的java中四种线程池及poolSize、corePoolSize、maximumPoolSize的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自定义RecyclerView动画——实
- 下一篇: c++学习笔记之模板