线程池能够复用线程,减少线程创建,销毁,恢复等状态切换的开销,提高程序的性能。一个线程池管理了一组工作线程,同时它还包括了一个用于放置等待执行的任务的队列。
ThreadPoolExecutor类中定义了一些与线程状态与活动线程数相关的一些变量,如下:
- 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;
-
-
- 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;
由如上可知:
ctl是一个AtomicInteger类型的原子对象。ctl记录了"线程池中的任务数量"和"线程池状态"2个信息。ctl共包括32位。其中,高3位表示"线程池状态",低29位表示"线程池中的任务数量"。
RUNNING -- 对应的高3位值是111 SHUTDOWN -- 对应的高3位值是000 STOP -- 对应的高3位值是001 TIDYING -- 对应的高3位值是010 TERMINATED -- 对应的高3位值是011
线程池各个状态之间的切换如下图所示:
线程池各个状态间的转换的详细解释如下所示。
1> RUNNING(111) -> SHUTDOWN(000) : 调用了shutdown方法,线程池实现了finalize方法,在里面调用了shutdown方法,因此shutdown可能是在finalize中被隐式调用的
2> (RUNNING(111) or SHUTDOWN(000)) -> STOP(001) 调用了shutdownNow方法
3> SHUTDOWN(000) -> TIDYING(010) : 当队列和线程池均为空的时候
4> STOP(001) -> TIDYING(010) : 当线程池为空的时候
5> TIDYING(010) -> TERMINATED(011) : terminated()方法调用完毕
说明:扩号后的3位数字表示ctl的高3位二进制值,并不关注低29位二进制的值
还有一些对常量的操作方法,只说明部分,其他的有兴趣自己可以去查看,如下:
- 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; }
来看一下ThreadPoolExecutor()中最主要的一个构造函数,如下:
- 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.corePoolSize = corePoolSize;
- this.maximumPoolSize = maximumPoolSize;
- this.workQueue = workQueue;
- this.keepAliveTime = unit.toNanos(keepAliveTime);
- this.threadFactory = threadFactory;
- this.handler = handler;
- }
调用Executors方法中的几个方法,如newCachedThreadPool()、newFixedThreadPool()时,都会间接调用上面的构造方法来初始化所有的线程池相关变量。
1、创建线程池并执行任务
有了Executor对象后,就可以调用execute()方法执行任务了。方法的源代码如下:
- public void execute(Runnable command) {
-
- if (command == null)
- throw new NullPointerException();
- int c = ctl.get();
-
-
-
-
-
-
- if (workerCountOf(c) < corePoolSize) {
-
-
-
-
-
- if (addWorker(command, true))
- 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))
- reject(command);
- }
当前活动的线程小于corePoolSize了,那么等于和大于corePoolSize怎么处理呢?
1> 当前活动的线程数量 >= corePoolSize 的时候,都是优先添加到队列中,直到队列满了才会去创建新的线程,在这里第20行的if语句已经体现出来了。这里利用了&&的特性,只有当第一个条件会真时才会去判断第二个条件,第一个条件是isRunning(),判断线程池是否处于RUNNING状态,因为只有在这个状态下才会接受新任务,否则就拒绝,如果正处于RUNNING状态,那么就加入队列,如果加入失败可能就是队列已经满了,这时候直接执行第29行。
2> 在execute()方法中,当 当前活动的线程数量 < corePoolSize 时,会执行addWorker()方法,关于addWorker(),它是用来直接新建线程用的,之所以叫addWorker而不是addThread是因为在线程池中,所有的线程都用一个Worker对象包装着,来看一下这个方法:
-
-
-
-
-
-
-
-
-
- private boolean addWorker(Runnable firstTask, boolean core) {
- retry:
- for (;;) {
- int c = ctl.get();
- int rs = runStateOf(c);
-
-
-
-
-
-
- if (rs >= SHUTDOWN &&
- ! (rs == SHUTDOWN &&
- firstTask == null &&
- ! workQueue.isEmpty()))
- return false;
-
- for (;;) {
-
- int wc = workerCountOf(c);
-
-
-
-
-
-
- if (wc >= CAPACITY ||
- wc >= (core ? corePoolSize : maximumPoolSize))
- return false;
-
- if (compareAndIncrementWorkerCount(c))
- break retry;
- c = ctl.get();
- if (runStateOf(c) != rs)
- continue retry;
-
- }
- }
-
-
- Worker w = new Worker(firstTask);
-
-
- Thread t = w.thread;
-
- final ReentrantLock mainLock = this.mainLock;
- mainLock.lock();
- try {
-
-
- int c = ctl.get();
- int rs = runStateOf(c);
-
-
-
-
-
-
-
-
- if (t == null ||
- (rs >= SHUTDOWN &&
- ! (rs == SHUTDOWN &&
- firstTask == null))) {
- decrementWorkerCount();
- tryTerminate();
- return false;
- }
-
- workers.add(w);
-
- int s = workers.size();
- if (s > largestPoolSize)
- largestPoolSize = s;
- } finally {
- mainLock.unlock();
- }
-
- t.start();
-
-
-
- if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted())
- t.interrupt();
-
- return true;
- }
那么在创建线程的时候,线程执行的是什么的呢?
我们前面提到Worker继承的其实也是Runnable,它在创建线程的时候是以自身作为任务传进先创建的线程中的,这段比较简单,我就不一一注释了,只是给出源代码给大家看吧。
Worker(Runnable firstTask) {
this.firstTask = firstTask;
//this指的是worker对象本身
this.thread = getThreadFactory().newThread(this);
}
它以自身的对象作为线程任务传进去,那么它的run方法又是怎样的呢?
public void run() {
runWorker(this);
}
竟然只有一句话调用runWorker()方法,这个可是重头戏,我们来看看,究竟运行的是什么。
-
-
-
-
-
-
- final void runWorker(Worker w) {
- Runnable task = w.firstTask;
- w.firstTask = null;
-
-
- boolean completedAbruptly = true;
- try {
-
- while (task != null || (task = getTask()) != null) {
- w.lock();
- clearInterruptsForTaskRun();
- try {
- beforeExecute(w.thread, 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);
- }
- }
下面就是线程在执行任务之前对线程池状态的一次判断:
-
-
-
-
-
- private void processWorkerExit(Worker w, boolean completedAbruptly) {
-
-
- if (completedAbruptly)
- decrementWorkerCount();
-
- final ReentrantLock mainLock = this.mainLock;
- mainLock.lock();
- try {
- completedTaskCount += w.completedTasks;
- workers.remove(w);
- } finally {
- mainLock.unlock();
- }
-
- tryTerminate();
-
- int c = ctl.get();
-
-
-
- if (runStateLessThan(c, STOP)) {
- if (!completedAbruptly) {
- int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
- if (min == 0 && ! workQueue.isEmpty())
- min = 1;
-
-
-
- if (workerCountOf(c) >= min)
- return;
- }
-
- addWorker(null, false);
- }
- }
前面我们的方法遇见过很多次tryTerminate()方法,到底他是怎样尝试结束线程池的呢?
-
-
-
- final void tryTerminate() {
- for (;;) {
- int c = ctl.get();
- if (isRunning(c) ||
- runStateAtLeast(c, TIDYING) ||
- (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
- return;
- if (workerCountOf(c) != 0) {
-
-
-
-
-
-
-
-
-
-
- interruptIdleWorkers(ONLY_ONE);
- return;
- }
-
- final ReentrantLock mainLock = this.mainLock;
- mainLock.lock();
- try {
-
-
-
-
-
- if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
- try {
- terminated();
- } finally {
- ctl.set(ctlOf(TERMINATED, 0));
-
-
-
-
-
- termination.signalAll();
- }
- return;
- }
- } finally {
- mainLock.unlock();
- }
-
- }
- }
2、关闭线程池
关闭时使用shutdown()方法,源码如下:
- public void shutdown() {
- final ReentrantLock mainLock = this.mainLock;
- mainLock.lock();
- try {
- checkShutdownAccess();
- advanceRunState(SHUTDOWN);
- interruptIdleWorkers();
- onShutdown();
- } finally {
- mainLock.unlock();
- }
- tryTerminate();
- }