今天我们专门聊聊ThreadPoolExecutor的拒绝策略

入口

我们还是需要回到最开始的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的线程池大小上尝试添加失败(addWorker(command, true))之后再次进行在maximumPoolSize大小上尝试添加(addWorker(null, false))。如果都失败了就会调用reject(command)。进行拒绝策略的处理。

final void reject(Runnable command) {
    handler.rejectedExecution(command, this);
}

reject会调用接口RejectedExecutionHandler的rejectedExecution方法.而RejectedExecutionHandler在ThreadPoolExecutor中有如下几个默认实现(都是内部类):

  1. AbortPolicy: 抛出一个RejectedExecutionException异常,然后抛弃任务.
  2. CallerRunsPolicy: 如果线程池没有关闭直接在线程池中执行被拒绝的任务,否则任务会被丢弃。
  3. DiscardPolicy: 直接丢弃被拒绝的任务,不做任何事.
  4. DiscardOldestPolicy: 如果线程池没有关闭,则将队列(workQueue)的队头任务(等待最久的任务)抛弃,然后尝试将被拒绝的任务再次添加到队列中。如果线程池已经关闭则直接丢弃任务

ThreadPoolExecutor的默认实现是AbortPolicy。