《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor (三)

这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭。

先来说说线程池的开启,这部分来看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;
    }

可以看到,尽管设定了corePoolSize,也就是Worker线程的数量,但是线程池开启的时候,默认是没有创建这些Worker线程的,但是ThreadPoolExecutor提供了prestartAllCoreThreads方法来开启所有的预设的Worker线程,以及prestartCoreThread尝试开启一个预设的Worker线程。

这里重点说说handler,也就是RejectedExecutionHandler,拒绝任务的处理类,ThreadPoolExecutor提供四种策略:

1. CallerRunsPolicy

该策略会在ThreadPoolExecutor没有关闭的情况,依旧运行任务

2. AbortPolicy

该策略会抛出一个RejectedExecutionException

3. DiscardPolicy

该策略直接忽略该任务,不会有任何动作

4. DiscardOldestPolicy

该策略会在ThreadPoolExecutor没有关闭的情况,丢弃下一个将要执行的任务,把该任务加入到执行队列。

接下来说说关闭,ThreadPoolExecutor提供了shutdown和shutdownNow两种方式,从字面上就能看出区别,后者会尝试结束正在运行的任务。

先来看shutdown:

public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(SHUTDOWN);
            interruptIdleWorkers();
            onShutdown(); // ScheduledThreadPoolExecutor的回调方法
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }

再看shutdownNow:

public List<Runnable> shutdownNow() {
        List<Runnable> tasks;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(STOP);
            interruptWorkers();
            tasks = drainQueue();
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
        return tasks;
    }

两个方法的代码非常相似,区别在于:

1. shutdownNow的状态设置为STOP,shutdown的状态是SHUTDOWN

2. shutdownNow会中断所有线程,也就是所有任务,而shutdown仅仅中断空闲线程,不会影响正在执行的任务。

3. shutdownNow会导出未执行的任务。

两个方法都用到的checkShutdownAccess方法主要是检查方法调用者是否有权限中断Worker线程。

advanceRunState方法用于设定线程的状态,如果状态值大于等于该状态值则会返回。关于状态值参看 《java.util.concurrent 包源码阅读》11 线程池系列之ThreadPoolExecutor 第一部分。

关于interruptIdleWorkers和interruptWorkers,在上一篇文章曾经说过Worker线程具备锁的功能,因此可以通过tryLock来判断Worker线程是否处于空闲状态,这是两个方法的区别所在。

这一部分写的有些凌乱,各位见谅。

猜你喜欢

转载自blog.csdn.net/wszhongguolujun/article/details/89709623