ThreadPoolExecutor部分重要成員變量:
1、AtomicInteger ctl
2宇整、workQueue
3瓶佳、corePoolSize
4、maximumPoolSize
5鳞青、keepAliveTime
6霸饲、handler
一为朋、AtomicInteger ctl
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
// Packing and unpacking ctl
private static int runStateOf(int c) { return c & ~CAPACITY; }
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
AtomicInteger類型的ctl代表了ThreadPoolExecutor中的控制狀態(tài),它是一個復(fù)核類型的成員變量厚脉,是一個原子整數(shù)习寸,借助高低位包裝了兩個概念:
- workerCount:線程池中當(dāng)前活動的線程數(shù)量,占據(jù)ctl的低29位傻工;
- runState:線程池運(yùn)行狀態(tài)霞溪,占據(jù)ctl的高3位,有RUNNING中捆、SHUTDOWN鸯匹、STOP、TIDYING泄伪、TERMINATED五種狀態(tài)殴蓬。
workerCount:
COUNT_BITS的定義代表了workerCount所占位數(shù):
private static final int COUNT_BITS = Integer.SIZE - 3;
//在Java中,一個int占據(jù)32位蟋滴,而COUNT_BITS的結(jié)果不言而喻染厅,Integer大小32減去3,就是29津函。
CAPACITY的定義限制了workerCount的理論最大活躍線程數(shù):
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
//運(yùn)算過程為1左移29位肖粮,也就是00000000 00000000 00000000 00000001 --> 001 0000 00000000 00000000 00000000,
//再減去1球散,就是 000 11111 11111111 11111111 11111111尿赚,
//前三位代表線程池運(yùn)行狀態(tài)runState,
//所以這里workerCount的理論最大值就應(yīng)該是29個1蕉堰,即536870911。
workerCount作為其中一個概念復(fù)合在AtomicInteger ctl中悲龟,ThreadPoolExecutor也提供了從AtomicInteger ctl中解析出workerCount的方法屋讶,如下:
private static int workerCountOf(int c) {
return c & CAPACITY;
}
//傳入的c代表的是ctl的值,即高3位為線程池運(yùn)行狀態(tài)runState须教,低29位為線程池中當(dāng)前活動的線程數(shù)量workerCount.
//將其與CAPACITY進(jìn)行與操作&皿渗,也就是與000 11111 11111111 11111111 11111111進(jìn)行與操作,
//c的前三位通過與000進(jìn)行與操作轻腺,無論c前三位為何值乐疆,最終都會變成000,也就是舍棄前三位的值贬养,
//而c的低29位與29個1進(jìn)行與操作挤土,c的低29位還是會保持原值,
//這樣就從AtomicInteger ctl中解析出了workerCount的值误算。
runState:
線程池運(yùn)行狀態(tài)仰美,它占據(jù)ctl的高3位迷殿,有RUNNING、SHUTDOWN咖杂、STOP庆寺、TIDYING、TERMINATED五種狀態(tài)诉字。我們先分別解釋下這五種狀態(tài):
- RUNNING:接受新任務(wù)懦尝,并處理隊(duì)列任務(wù)
//Accept new tasks and process queued tasks
private static final int RUNNING = -1 << COUNT_BITS;
-1在Java底層是由32個1表示的,左移29位的話壤圃,即111 00000 00000000 00000000 00000000导披,也就是低29位全部為0,高3位全部為1的話埃唯,表示RUNNING狀態(tài)撩匕,即-536870912;
- SHUTDOWN:不接受新任務(wù)墨叛,但會處理隊(duì)列任務(wù)
//Don't accept new tasks, but process queued tasks
private static final int SHUTDOWN = 0 << COUNT_BITS;
0在Java底層是由32個0表示的止毕,無論左移多少位,還是32個0漠趁,即000 00000 00000000 00000000 00000000扁凛,也就是低29位全部為0,高3位全部為0的話闯传,表示SHUTDOWN狀態(tài)谨朝,即0。
- STOP:不接受新任務(wù)甥绿,不會處理隊(duì)列任務(wù)字币,而且會中斷正在處理過程中的任務(wù)
//Don't accept new tasks, don't process queued tasks,
//and interrupt in-progress tasks
private static final int STOP = 1 << COUNT_BITS;
1在Java底層是由前面的31個0和1個1組成的,左移29位的話共缕,即001 00000 00000000 00000000 00000000洗出,也就是低29位全部為0,高3位為001的話图谷,表示STOP狀態(tài)翩活,即536870912;
- TIDYING:所有的任務(wù)已結(jié)束便贵,workerCount為0彬坏,線程過渡到TIDYING狀態(tài)鲁豪,將會執(zhí)行terminated()鉤子方法。
/*
All tasks have terminated, workerCount
is zero,the thread transitioning to
state TIDYING will run the terminated() hook method
*/
private static final int TIDYING = 2 << COUNT_BITS;
2在Java底層是由前面的30個0和1個10組成的,左移29位的話箩退,即010 00000 00000000 00000000 00000000,也就是低29位全部為0,高3位為010的話,表示TIDYING狀態(tài)魂毁,即1073741824。
- TERMINATED:terminated()方法已經(jīng)完成
//terminated() has completed
private static final int TERMINATED = 3 << COUNT_BITS;
3在Java底層是由前面的30個0和1個11組成的出嘹,左移29位的話席楚,即011 00000 00000000 00000000 00000000,也就是低29位全部為0税稼,高3位為011的話烦秩,表示TERMINATED狀態(tài),即1610612736郎仆。
由上面我們可以得知只祠,運(yùn)行狀態(tài)的值按照RUNNING-->SHUTDOWN-->STOP-->TIDYING-->TERMINATED順序值是遞增的,這些值之間的數(shù)值順序很重要扰肌。隨著時間的推移抛寝,運(yùn)行狀態(tài)單調(diào)增加,但是不需要經(jīng)過每個狀態(tài)曙旭。那么盗舰,可能存在的線程池狀態(tài)的轉(zhuǎn)換是什么呢?如下:
* RUNNING -> SHUTDOWN
* On invocation of shutdown(), perhaps implicitly in finalize()
* (RUNNING or SHUTDOWN) -> STOP
* On invocation of shutdownNow()
* SHUTDOWN -> TIDYING
* When both queue and pool are empty
* STOP -> TIDYING
* When pool is empty
* TIDYING -> TERMINATED
* When the terminated() hook method has completed
*
- RUNNING -> SHUTDOWN:調(diào)用shutdown()方法后桂躏,或者線程池實(shí)現(xiàn)了finalize方法钻趋,在里面調(diào)用了shutdown方法,即隱式調(diào)用剂习。
- (RUNNING or SHUTDOWN) -> STOP:調(diào)用shutdownNow()方法后蛮位。
- SHUTDOWN -> TIDYING:線程池和隊(duì)列均為空時。
- STOP -> TIDYING:線程池為空時鳞绕。
- TIDYING -> TERMINATED:terminated()鉤子方法完成時失仁。
接下來看看如何從ctl中提取runState:
private static int runStateOf(int c) { return c & ~CAPACITY; }
~ 是按位取反的意思,CAPACITY表示的是高位的3個0猾昆,和低位的29個1陶因,而~CAPACITY則表示高位的3個1,2低位的9個0垂蜗,然后再與入?yún)執(zhí)行按位與操作,即高3位保持原樣解幽,低29位全部設(shè)置為0贴见,也就獲取了線程池的運(yùn)行狀態(tài)runState。
最后看一下這個方法:
private static int ctlOf(int rs, int wc) { return rs | wc; }
將runState和workerCount做或操作|處理躲株,即用runState的高3位片部,workerCount的低29位填充的數(shù)字,而默認(rèn)傳入的runState霜定、workerCount分別為RUNNING和0档悠。
接下來看一下其他幾個重要的成員變量:
/**
* The queue used for holding tasks and handing off to worker
* threads. We do not require that workQueue.poll() returning
* null necessarily means that workQueue.isEmpty(), so rely
* solely on isEmpty to see if the queue is empty (which we must
* do for example when deciding whether to transition from
* SHUTDOWN to TIDYING). This accommodates special-purpose
* queues such as DelayQueues for which poll() is allowed to
* return null even if it may later return non-null when delays
* expire.
*/
private final BlockingQueue<Runnable> workQueue;
/**
* Lock held on access to workers set and related bookkeeping.
* While we could use a concurrent set of some sort, it turns out
* to be generally preferable to use a lock. Among the reasons is
* that this serializes interruptIdleWorkers, which avoids
* unnecessary interrupt storms, especially during shutdown.
* Otherwise exiting threads would concurrently interrupt those
* that have not yet interrupted. It also simplifies some of the
* associated statistics bookkeeping of largestPoolSize etc. We
* also hold mainLock on shutdown and shutdownNow, for the sake of
* ensuring workers set is stable while separately checking
* permission to interrupt and actually interrupting.
*/
private final ReentrantLock mainLock = new ReentrantLock();
/**
* Set containing all worker threads in pool. Accessed only when
* holding mainLock.
*/
private final HashSet<Worker> workers = new HashSet<Worker>();
/**
* Wait condition to support awaitTermination
*/
private final Condition termination = mainLock.newCondition();
/**
* Tracks largest attained pool size. Accessed only under
* mainLock.
*/
private int largestPoolSize;
/**
* Counter for completed tasks. Updated only on termination of
* worker threads. Accessed only under mainLock.
*/
private long completedTaskCount;
/*
* All user control parameters are declared as volatiles so that
* ongoing actions are based on freshest values, but without need
* for locking, since no internal invariants depend on them
* changing synchronously with respect to other actions.
*/
/**
* Factory for new threads. All threads are created using this
* factory (via method addWorker). All callers must be prepared
* for addWorker to fail, which may reflect a system or user's
* policy limiting the number of threads. Even though it is not
* treated as an error, failure to create threads may result in
* new tasks being rejected or existing ones remaining stuck in
* the queue.
*
* We go further and preserve pool invariants even in the face of
* errors such as OutOfMemoryError, that might be thrown while
* trying to create threads. Such errors are rather common due to
* the need to allocate a native stack in Thread.start, and users
* will want to perform clean pool shutdown to clean up. There
* will likely be enough memory available for the cleanup code to
* complete without encountering yet another OutOfMemoryError.
*/
private volatile ThreadFactory threadFactory;
/**
* Handler called when saturated or shutdown in execute.
*/
private volatile RejectedExecutionHandler handler;
/**
* Timeout in nanoseconds for idle threads waiting for work.
* Threads use this timeout when there are more than corePoolSize
* present or if allowCoreThreadTimeOut. Otherwise they wait
* forever for new work.
*/
private volatile long keepAliveTime;
/**
* If false (default), core threads stay alive even when idle.
* If true, core threads use keepAliveTime to time out waiting
* for work.
*/
private volatile boolean allowCoreThreadTimeOut;
/**
* Core pool size is the minimum number of workers to keep alive
* (and not allow to time out etc) unless allowCoreThreadTimeOut
* is set, in which case the minimum is zero.
*/
private volatile int corePoolSize;
/**
* Maximum pool size. Note that the actual maximum is internally
* bounded by CAPACITY.
*/
private volatile int maximumPoolSize;
/**
* The default rejected execution handler
*/
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
private final BlockingQueue<Runnable> workQueue; //任務(wù)緩存隊(duì)列廊鸥,用來存放等待執(zhí)行的任務(wù)
private final ReentrantLock mainLock = new ReentrantLock(); //線程池的主要狀態(tài)鎖,對線程池狀態(tài)(比如線程池大小
//辖所、runState等)的改變都要使用這個鎖
private final HashSet<Worker> workers = new HashSet<Worker>(); //用來存放工作集
private volatile long keepAliveTime; //線程存貨時間
private volatile boolean allowCoreThreadTimeOut; //是否允許為核心線程設(shè)置存活時間
private volatile int corePoolSize; //核心池的大卸杷怠(即線程池中的線程數(shù)目大于這個參數(shù)時,提交的任務(wù)會被放進(jìn)任務(wù)緩存隊(duì)列)
private volatile int maximumPoolSize; //線程池最大能容忍的線程數(shù)
private volatile int poolSize; //線程池中當(dāng)前的線程數(shù)
private volatile RejectedExecutionHandler handler; //任務(wù)拒絕策略
private volatile ThreadFactory threadFactory; //線程工廠缘回,用來創(chuàng)建線程
private int largestPoolSize; //用來記錄線程池中曾經(jīng)出現(xiàn)過的最大線程數(shù)
private long completedTaskCount; //用來記錄已經(jīng)執(zhí)行完畢的任務(wù)個數(shù)
二吆视、workQueue:
阻塞隊(duì)列,用來存儲等待執(zhí)行的任務(wù)酥宴,這里的阻塞隊(duì)列有以下幾種選擇:
ArrayBlockingQueue:基于數(shù)組的先進(jìn)先出隊(duì)列啦吧,此隊(duì)列創(chuàng)建時必須指定大小拙寡;
LinkedBlockingQueue:基于鏈表的先進(jìn)先出隊(duì)列授滓,如果創(chuàng)建時沒有指定此隊(duì)列大小,則默認(rèn)為Integer.MAX_VALUE肆糕;
synchronousQueue:這個隊(duì)列比較特殊般堆,它不會保存提交的任務(wù),而是將直接新建一個線程來執(zhí)行新來的任務(wù)擎宝。
三郁妈、corePoolSize:
核心池的大小,這個參數(shù)跟后面講述的線程池的實(shí)現(xiàn)原理有非常大的關(guān)系绍申。在創(chuàng)建了線程池后噩咪,默認(rèn)情況下,線程池中并沒有任何線程极阅,而是等待有任務(wù)到來才創(chuàng)建線程去執(zhí)行任務(wù)胃碾,除非調(diào)用了prestartAllCoreThreads()或者prestartCoreThread()方法,從這2個方法的名字就可以看出筋搏,是預(yù)創(chuàng)建線程的意思仆百,即在沒有任務(wù)到來之前就創(chuàng)建corePoolSize個線程或者一個線程。默認(rèn)情況下奔脐,在創(chuàng)建了線程池后俄周,線程池中的線程數(shù)為0,當(dāng)有任務(wù)來之后髓迎,就會創(chuàng)建一個線程去執(zhí)行任務(wù)峦朗,當(dāng)線程池中的線程數(shù)目達(dá)到corePoolSize后,就會把到達(dá)的任務(wù)放到緩存隊(duì)列當(dāng)中排龄。
四波势、maximumPoolSize:
線程池最大線程數(shù),這個參數(shù)也是一個非常重要的參數(shù),它表示在線程池中最多能創(chuàng)建多少個線程尺铣;
五拴曲、keepAliveTime:
表示線程沒有任務(wù)執(zhí)行時最多保持多久時間會終止。默認(rèn)情況下凛忿,只有當(dāng)線程池中的線程數(shù)大于corePoolSize時澈灼,keepAliveTime才會起作用,直到線程池中的線程數(shù)不大于corePoolSize侄非,即當(dāng)線程池中的線程數(shù)大于corePoolSize時蕉汪,如果一個線程空閑的時間達(dá)到keepAliveTime,則會終止逞怨,直到線程池中的線程數(shù)不超過corePoolSize者疤。但是如果調(diào)用了allowCoreThreadTimeOut(boolean)方法,在線程池中的線程數(shù)不大于corePoolSize時叠赦,keepAliveTime參數(shù)也會起作用驹马,直到線程池中的線程數(shù)為0;
六除秀、handler:
表示當(dāng)拒絕處理任務(wù)時的策略糯累,有以下四種取值:
//當(dāng)線程池的任務(wù)緩存隊(duì)列已滿并且線程池中的線程數(shù)目達(dá)到maximumPoolSize,如果還有任務(wù)到來就會采取任務(wù)拒絕策略
ThreadPoolExecutor.AbortPolicy:丟棄任務(wù)并拋出RejectedExecutionException異常册踩。
ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù)泳姐,但是不拋出異常。
ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊(duì)列最前面的任務(wù)暂吉,然后重新嘗試執(zhí)行任務(wù)(重復(fù)此過程)
ThreadPoolExecutor.CallerRunsPolicy:由調(diào)用線程處理該任務(wù)