• 《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 第一部分。

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

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

  • 相关阅读:
    C#免注册调用大漠插件
    python字符串拼接方式
    小素数
    欧几里得算法
    spark中代码的执行位置(Driver or Executer)
    Pdf添加水印功能
    2022.06.10软件更新公告
    JS对象删除空值
    Flink读写Hive文档
    webpack打包后*.js等静态资源找不到问题解决小记
  • 原文地址:https://www.cnblogs.com/wanly3643/p/3924617.html
Copyright © 2020-2023  润新知