Skip to content

Java 线程池生命周期

Published: at 17:43:41

问题

(1)线程池的状态有哪些?

(2)各种状态下对于任务队列中的任务有何影响?

看源码线程池状态

ThreadPoolExecutor.class

// 状态控制  ctl的高三位保存运行状态
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//用二进制补码形式表示整型值的位数, 值为32-3
private static final int COUNT_BITS = Integer.SIZE - 3;
// 00‭10 0000 0000 0000 0000 0000 0000 0000‬, 一共32位
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

// runState is stored in the high-order bits
// 1110 0000 0000 0000 0000 0000 0000 0000‬
private static final int RUNNING    = -1 << COUNT_BITS;

// 0000 0000 0000 0000 0000 0000 0000 0000‬
private static final int SHUTDOWN   =  0 << COUNT_BITS;

// 00‭10 0000 0000 0000 0000 0000 0000 0000‬
private static final int STOP       =  1 << COUNT_BITS;

// 0‭100 0000 0000 0000 0000 0000 0000 0000‬
private static final int TIDYING    =  2 << COUNT_BITS;

// 0‭110 0000 0000 0000 0000 0000 0000 0000‬
private static final int TERMINATED =  3 << COUNT_BITS;
// 线程池的状态
private static int runStateOf(int c)     { return c & ~CAPACITY; }
// 线程池中工作线程的数量
private static int workerCountOf(int c)  { return c & CAPACITY; }
// 计算ctl的值,等于运行状态“加上”线程数量
private static int ctlOf(int rs, int wc) { return rs | wc; }

从上面可以看出:

  1. 线程池的状态一共有五种,分别是
    1. RUNNING
      • 表示可接受新任务,且可执行队列中的任务
    2. SHUTDOWN
      • 表示不接受新任务,但可执行队列中的任务
    3. STOP
      • 表示不接受新任务,且不再执行队列中的任务,且中断正在执行的任务
    4. TIDYING
      • 所有任务已经中止,且工作线程数量为0,最后变迁到这个状态的线程将要执行terminated()钩子方法,只会有一个线程执行这个方法
    5. TERMINATED
      • 中止状态,已经执行完terminated()钩子方法
  2. ctl的高三位保存运行状态,低29位保存工作线程的数量,也就是说线程的数量最多只能有(2^29-1)个,也就是上面的CAPACITY, 不是(2^31)-1

线程池的任务流转图: untitled

过程:

  1. 新建时, 初始状态为RUNNING
  2. 执行shutdown()方法 —> 状态变为SHUTDOWN
  3. 执行shutdownNow()方法 —> 状态变为STOP
  4. shutdown()或shutdownNow()方法执行完毕, 且所有任务也已经终止, 工作中的线程数量为0 , 状态变为TIDYING
  5. 状态变为TIDYING后会有一个线程来执行terminated()钩子方法,最后状态变为终止状态TERMINATED

源码分析

1)RUNNING

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

2)SHUTDOWN

private final ReentrantLock mainLock = new ReentrantLock();

public void shutdown() {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        // 检查是否有关闭权限

        checkShutdownAccess();
        //变更状态为SHUTDOWN

        advanceRunState(SHUTDOWN);       
        // 标记空闲线程为中断状态

        interruptIdleWorkers();
        onShutdown(); // hook for ScheduledThreadPoolExecutor
    } finally {
        mainLock.unlock();
    }
    //  shutdown 后尝试终止

    tryTerminate();
}

3)STOP

public List<Runnable> shutdownNow() {
    List<Runnable> tasks;
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        checkShutdownAccess();        
        //变更状态为STOP
        advanceRunState(STOP);
        interruptWorkers();
        // 将任务队列加入到新的列表中返回

        tasks = drainQueue();
    } finally {
        mainLock.unlock();
    }
    tryTerminate();
    return tasks;
}

4)TIDYING

final void tryTerminate() {
    for (;;) {
        int c = ctl.get();
        if (isRunning(c) ||
            runStateAtLeast(c, TIDYING) ||
            (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
            return;
        // 工作线程数量不为0,不会执行后续代码

        if (workerCountOf(c) != 0) { // Eligible to terminate
            interruptIdleWorkers(ONLY_ONE);
            return;
        }

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            // CAS修改状态为TIDYING状态

            if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                try {
                    //执行terminated钩子方法

                    terminated();
                } finally {
                    // CAS修改状态为TERMINATED状态

                    ctl.set(ctlOf(TERMINATED, 0));
                    termination.signalAll();
                }
                return;
            }
        } finally {
            mainLock.unlock();
        }
        // else retry on failed CAS
    }
}

修改状态为TIDYING后执行terminated()方法,最后修改状态为TERMINATED,标志着线程池真正消亡