关闭一个ExecutorService,有两个方法可以使用–shutdown和shutdownNow。
shutdown在关闭线程池前,会等待所有线程执行完;shutdownNow会立刻关闭线程池,并停止所有线程。
isTerminated();判断线程池中是否所有的任务都完成执行。必须先执行关闭方法shutdown或shutdownNow,否则这个方法只会返回false。
boolean awaitTermination(long timeout, TimeUnit unit)在发起shutdown请求后,阻塞当前线程直到线程池内所有线程执行完成,或者当前线程被中断,或者超时。
Future submit(Callable task); 提交一个任务给线程池,返回一个Future对象,调用get方法,如果目标线程没有执行完,则会阻塞。
获取一个线程池,使用Executors(该类不能被实例化)类,创建一个固定大小的线程池
public static ExecutorService newFixedThreadPool(int nThreads) {
// 池中corePoolSize ,池中的最大线程数,corePoolSize 之外的额外数量的空闲线程的存活时间,保存待执行的任务队列
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
*分为3步:
*
* 1. 线程池中运行的线程少于corePoolSize 的值,则新增一个worker到线程池中(调用 addWorker 会原子性的检查runState 和 workerCount, 以保证不会加入过量的线程)
*
* 2. 第一步失败了的话,task入队, 需要再次检查是否已经添加了一个线程或者线程池已经shutdown,检查状态,如果线程池停止了的话,就不入队了。
*
* 3. 如果不能入队,则尝试加入一个新线程. 如果失败, 说明线程池已经关闭或者饱和了(超过的线程池的最大值),拒绝此次任务.
*/
int c = ctl.get();//初始值 101 0000....00
if (workerCountOf(c) < corePoolSize) {
//private static final int CAPACITY = (1 << COUNT_BITS) - 1;
//CAPACITY 000 111....111
if (addWorker(command, true))//会对ctl 加1
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {//线程池的线程数量超过了核心池的数量,就先入队列。
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))//入队列失败,则尝试新创建worker,此时不能超过线程池的最大值
reject(command);
}
addWorker方法,添加一个任务到线程池中,并启动。addWorker时要求同步(适应mainLock):
//只有线程池是running状态,才能添加任务。
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);//通过位运算,取出状态位
//Running 111 ,SHUTDOWN 000,STOP 001。
// 如果线程池的状态不是RUNNING,也不是shutdown的话,直接返回false.(TERMINATED ,TIDYING,STOP)
//如果是shutdown状态,firstTask 不是Null也就是说队列中还有任务,也直接返回false
//如果是shutdown状态,firstTask 是Null,队列是空的,也返回false
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);//如果发现ctl>corePoolSize ,也返回false
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
if (compareAndIncrementWorkerCount(c))//没有锁竞争,更新成功,终止循环
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)//largestPoolSize,woker的达到过的最大值
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
每一个worker的run线程,调用了runWorker方法,woker如果创建时属于core线程,则第一个任务task就是创建时传的参数,执行完当前任务之后,它会从workers队列中取出下一个任务接着执行:
public void run() {
runWorker(this);
}
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) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
woker在执行前,需要同步,同步会先尝试获取锁,在没有被占用的情况下才能获得,如果锁被占用也就是state!=0,则会入队并阻塞(阻塞前还会尝试再判断是不是队列头,然后尝试获取锁);
protected boolean tryAcquire(int unused) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
直接使用execute执行任务,是没有返回值的,如果要获取结果,那么使用submit方法,submit方法最后一个调用了execute来执行任务的,只是它对task做了一层包装,包装后的futureTask类有3个重要的方法,run方法,get方法,cancell方法。
首先是run方法,判断状态,所以这种任务只能执行一次。
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
protected boolean tryAcquire(int unused) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
线程启动失败的话,tryTerminate();该方法在中断前,会判断队列中是否有任务没有被执行,如果有,就什么都不做。没有额外任务的话,会优先关闭一个空闲线程,是否关闭所有的空闲线程,可以根据ONLY_ONE属性设置。