關于線程池的幾個參數的含義,我們就不多說了,下面我們通過源碼看下這幾個參數分别是在什麼地方使用到的:
核心池大小與最大池大小是在執行任務的時候用到的,這裡我們不多說。
當線程池中沒有任務,線程池就會維持核心池大小的線程,這個源碼如下:
當線程進來會先被封裝成一個Worker類,這個類實作了Runnable接口,如下:
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
/** Delegates main run loop to outer runWorker */
public void run() {
runWorker(this);
}
實際上,線程池建立的線程,是先執行的這個Worker類的run方法,然後才執行Runnable類的run方法,即為封裝了一層,如下:
Runnable task = w.firstTask;
task.run();
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
runWorker中有一個getTask()方法,我們着重來看這個方法,裡面就有為什麼核心線程數的線程可以一直存在的秘密:
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
int wc = workerCountOf(c);
// Are workers subject to culling?
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
上面可以看到,如果目前線程數(wc>corePoolSize)的話,則執行阻塞隊列的poll方法,否則執行take()方法,而poll方法中,傳入了一個keepAliveTIme的參數,此時空閑線程會等keepalive的時間,如果取不到資料則傳回空,目前線程走完結束,如果執行take()方法,則會一直阻塞,知道取到資料,這就是為什麼核心線程池一直存在的原因。
同時我們還看到一個allowCoreThreadTimeOut參數,這個參數預設值是false,如果不想讓核心線程存在也可以主動将此參數設定為true。
另外還有一個可以說下的就i是ThreadFactory,它建立線程的方式跟我們平時建立線程用的方式是一樣的:
this.thread = getThreadFactory().newThread(this);
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
也就是new了一個線程這樣而已。ThreadFactory隻是建立線程用的,線上程建立好後,就跟ThreadFactory完全沒有關系了。