远方聂努达

V1

2022/03/16阅读:14主题:极简黑

线程池的execute()方法是如何执行的?

线程池的 execute() 方法是如何执行的?

执行流程

一般情况下,我们使用线程池经常会用到它的 execute() 方法去提交任务,那么你知道它的执行流程吗?我们首先来看下源码实现:

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        
         and so reject the task.
        
        int c = ctl.get();
         // 这里判断的是当前工作的线程数小于核心线程数
        if (workerCountOf(c) < corePoolSize) {
           // 如果小于则创建新的线程执行此任务
            if (addWorker(commandtrue))
                return;
            c = ctl.get();
        }
        // 判断线程池是否处于运行状态,如果是则把任务添加到队列
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            // 再次检线程池是否处于运行状态,防止在第一次校验通过后线程池关闭
            // 如果是非运行状态,则将刚加入队列的任务移除
            if (! isRunning(recheck) && remove(command))
                reject(command);
                // 如果线程池的线程数为 0 时(当 corePoolSize 设置为 0 时会发生)
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
         // 核心线程都在工作且队列已满,尝试新启动一个线程执行失败
        else if (!addWorker(commandfalse))
            reject(command);
    }

根据以上源码我们可以得出,execute() 方法的执行流程是:第一步先判断当前线程数是否大于核心线程数,如果结果为 false,则新建线程并执行任务;如果结果为 true,第二步则判断任务队列是否已满,如果结果为 false,则把任务添加到任务队列中等待线程执行,第三步则判断当前线程数量是否超过最大线程数,如果结果为 false,则新建线程执行此任务,否则将执行线程池的拒绝策略。

线程池拒绝策略

当任务过多且线程池的任务队列已满时,此时就会执行线程池的拒绝策略,线程池的拒绝策略默认有以下 4 种:

  • AbortPolicy:中止策略,线程池会抛出 RejectedExecutionException异常并中止执行此任务;
  • CallerRunsPolicy:把任务交给添加此任务的(main)线程来执行;
  • DiscardPolicy:忽略此任务,忽略最新的一个任务;
  • DiscardOldestPolicy:忽略旧的任务,最先加入队列的任务。

线程池默认的拒绝策略为 AbortPolicy 中止策略。

自定义拒绝策略

通过 new RejectedExecutionHandler,并重写 rejectedExecution() 方法来实现自定义拒绝策略。

微信搜索:R先生专栏,点关注,不迷路!

- END -

分类:

后端

标签:

后端

作者介绍

远方聂努达
V1