java线程池ThreadPoolExecutor的拒绝策略RejectedExecutionHandler

近期在面试时问题时问到了 ThreadPoolExecutor 的拒绝策略 RejectedExecutionHandler 的实现 CallerRunsPolicy,之前没深入思考过,在此记录一下。

拒绝策略

RejectedExecutionHandler 源码

package java.util.concurrent;

/**
 * A handler for tasks that cannot be executed by a {@link ThreadPoolExecutor}.
 *
 * @since 1.5
 * @author Doug Lea
 */
public interface RejectedExecutionHandler {

    /**
     * Method that may be invoked by a {@link ThreadPoolExecutor} when
     * {@link ThreadPoolExecutor#execute execute} cannot accept a
     * task.  This may occur when no more threads or queue slots are
     * available because their bounds would be exceeded, or upon
     * shutdown of the Executor.
     *
     * 

In the absence of other alternatives, the method may throw * an unchecked {@link RejectedExecutionException}, which will be * propagated to the caller of {@code execute}. * * @param r the runnable task requested to be executed * @param executor the executor attempting to execute this task * @throws RejectedExecutionException if there is no remedy */ void rejectedExecution(Runnable r, ThreadPoolExecutor executor); }

具体的实现类在 ThreadPoolExecutor 中,内置的拒绝策略如下

AbortPolicy

java线程池ThreadPoolExecutor的拒绝策略RejectedExecutionHandler_第1张图片

如果在使用 ThreadPoolExecutor 时未指定 RejectedExecutionHandler 参数,则使用默认的拒绝策略 AbortPolicy。可以看到源码是直接抛出异常。

java线程池ThreadPoolExecutor的拒绝策略RejectedExecutionHandler_第2张图片

java线程池ThreadPoolExecutor的拒绝策略RejectedExecutionHandler_第3张图片

java线程池ThreadPoolExecutor的拒绝策略RejectedExecutionHandler_第4张图片 

DiscardPolicy

java线程池ThreadPoolExecutor的拒绝策略RejectedExecutionHandler_第5张图片

顾名思义,针对提交的任务进行丢弃。看源码针对提交的任务不做处理,符合丢弃的思想。

DiscardOldestPolicy

java线程池ThreadPoolExecutor的拒绝策略RejectedExecutionHandler_第6张图片

针对提交的任务将未处理的最老的任务丢弃掉,即调用了 BlockingQueue#poll() 将队列头上的任务给移除掉,接下来将任务进行添加等待被执行。

CallerRunsPolicy

java线程池ThreadPoolExecutor的拒绝策略RejectedExecutionHandler_第7张图片

看到名字的意思是调用者执行,看到源码的执行逻辑是直接调用 Runnable#run(),没有调用 Thread#start(),这样就不会通过操作系统单独创建线程来处理任务,对应的逻辑处理直接在当前调用 execute() 的线程上处理。

多线程的任务执行实际上通过 Thread#start() 来实现的,在调用 start() 后会进入 READY 状态,等待 cpu 调度执行,被调度后进入 RUNNING 状态,执行对应的 run() 中的逻辑。

通过 Thread#start() 触发的任务是异步执行的。

如果直接调用 Thread#run(),就是一个普通方法,执行是同步的。

在 ThreadPoolExecutor 中通过 ThreadFactory 来创建,如果未指定,默认实现类是 Executors#defaultThreadFactory(),创建的线程是用户线程,对应的线程类是 ThreadPoolExecutor  的内部类 Worker(继承了抽象类 AbstractQueuedSynchronizer 并且实现了接口 Runnable)。

java线程池ThreadPoolExecutor的拒绝策略RejectedExecutionHandler_第8张图片

在线程池中建议使用此策略,可以防止在执行过程中任务丢失的问题。

CallerRunsPolicy 和 DiscardOldestPolicy 的任务执行建立在线程池在没有结束的基础上,否则任务被丢弃。

之前自己写的文章

https://blog.csdn.net/zlpzlpzyd/article/details/124250907

https://blog.csdn.net/zlpzlpzyd/article/details/133500502

参考链接

https://blog.csdn.net/weixin_68105699/article/details/126474048

你可能感兴趣的:(线程池,java)