ava线程池ThreadPoolExecutor的keepAliveTime=0时,表示超过core线程数的线程在空闲时立即结束
今天同事突然提出問題說用哪個線程池好,newFixedThreadPool和newCacheThreadPool里選擇,說固定大小線程池keepAliveTime=0,線程空閑會立馬回收線程從而節約資源,然后另外一個同事說,0是代表永遠不回收,我記憶里也是記得0是永久存活,因為網上很多博客啊,資料啊都是說的0表示線程永久存活在空閑的時候。前面那位同事也是從字面上認為的,沒有經過驗證,覺得-1才是永久不回收,然后各自進行了一波研究分析。
經過看源碼,發現keepAliveTime<0是不行的,直接報錯,也就是同事的猜測-1才是不回收 是錯誤的,看下面代碼圖示(別問我怎么給代碼里部分標紅,直接用瀏覽器F12自己編輯頁面寫標簽樣式進去的。。)
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;
? ? }
然后找keepAliveTime的使用一時半會也沒找到,就用代碼測試了,發現設置keepAliveTime=0核心線程數確實沒有回收,后面同事說在并發病程的藝術那本書上有一段描述
“當線程池中的線程數大于corePoolSize時,keepAliveTime為多余的空閑線程等待新任務的 最長時間,超過這個時間后多余的線程將被終止。這里把keepAliveTime設置為0L,意味著多余 的空閑線程會被立即終止。”
同事又開始迷茫了,我一開始沒細看,覺得說的不對,后面反復閱讀,發現這段文字描述的是說keepAliveTime控制的是非核心線程數的回收,也就是0的時候,非核心線程數會在空閑的時候回收,并不是說核心的會回收。
為了驗證結果,我們就用代碼進行了測試,測試代碼如下:
package com.xhs.concurrent.threaddemo.sync;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
?
/**
?* @author xuhan ?build ?2019/4/23
?*/
public class ExecutorsDemo implements Runnable{
?
? ? private int i=0;
?
? ? public ExecutorsDemo(int i) {
? ? ? ? this.i = i;
? ? }
? ? public static void main(String[] args) {
? ? ? ? ThreadPoolExecutor executor = new ThreadPoolExecutor(1,2,0, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(1));
? ? ? ? for(int i=0;i<3;i++){
? ? ? ? ? ? executor.execute(new ExecutorsDemo(i));
? ? ? ? }
? ? ? ? while(true){
? ? ? ? ? ? System.out.println("總線程數:"+executor.getPoolSize()+"當前活躍線程數:"+executor.getActiveCount());
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? TimeUnit.SECONDS.sleep(1);
? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? @Override
? ? public void run() {
? ? ? ? System.out.println("i="+i+" Thread = "+Thread.currentThread().getName());
? ? ? ? if(i>=1){
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? TimeUnit.SECONDS.sleep(1);
? ? ? ? ? ? ? ? System.out.println("i="+i+" sleep 1 s結束");
? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }else{
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? TimeUnit.SECONDS.sleep(3);
? ? ? ? ? ? ? ? System.out.println("i="+i+" sleep 3 s結束");
? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
設置核心線程數和非核心線程數分別為1個,隊列容量為1,進入3個runnable:
第一個創建主線程,第二個進入隊列,第三個則創建非主線程運行,
輸出結果為
i=0 Thread = pool-1-thread-1
i=2 Thread = pool-1-thread-2
總線程數:2當前活躍線程數:2
總線程數:2當前活躍線程數:2
i=2 sleep 1 s結束
i=1 Thread = pool-1-thread-2
總線程數:2當前活躍線程數:2
總線程數:2當前活躍線程數:2
i=1 sleep 1 s結束
總線程數:1當前活躍線程數:1
總線程數:1當前活躍線程數:1
i=0 sleep 3 s結束
總線程數:1當前活躍線程數:0
可以看到非核心數線程執行完畢之后,隊列中的task進入繼續執行,等再次進入隊列的task結束后,可以看到總線程數減少了1,而等核心線程執行完畢后,發現總線程數沒有減少,但活躍線程數減少,也就是核心線程數沒有回收。書上說的是正確的,大部分網上的博客說的keepAliveTime=0永久不回收是有出入的。
如果要設置核心線程的回收,則需要設置
executor.allowCoreThreadTimeOut(true);
但這是keepAliveTime必須要>0才行,否則會拋出異常!!!
throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
如果看了之后覺得有問題,希望各位指點一番!!謝謝!!
————————————————
版權聲明:本文為CSDN博主「xuhangsong」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/xuhangsong/article/details/89474989
總結
以上是生活随笔為你收集整理的ava线程池ThreadPoolExecutor的keepAliveTime=0时,表示超过core线程数的线程在空闲时立即结束的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 胆囊炎能不能吃鱼油
- 下一篇: Ctr点击率预估理论基础及项目实战