面试题:线程池的底层工作原理

线程池的几个重要的参数:

1、corePoolSize:线程池的核心线程数(也是默认线程数)

2、maximumPoolSize:最大线程数

3、keepAliveTime:允许的线程最大空闲时间(单位/秒)

线程池内部是通过队列+线程实现的,当我们利用线程池执行任务时:

  • 如果此时线程池中的线程数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务,

  • 如里此时线程池中的线程数量等于corePoolSize,但是缓冲队列workQueue未满,那么任务被放入缓冲队列。

  • 如果此时线程池中的线程数量大于等于corePoolSize,缓中队列workQueue满,并且线程池中的数量小于maximumPooISize,建新的线程来外理被添加的任务。

  • 如果此时线程池中的线程数量大于corePoosize,缓冲队列workQueue满,并目线程池中的数量等于maximumPoosize,那么通过 handler所指定的策略来处理此任务。

  • 当线程池中的线程数量大于 corePoolsize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程可以动态的调整池中的线程数。

线程池的拒绝策略:指的是RejectedExecutionHandler接口的实现类。

在线程池接口的源代码中,可以发现ThreadPoolExecutor接口内置了4种拒绝策略。

java 复制代码
package java.util.concurrent;


public class ThreadPoolExecutor extends AbstractExecutorService {

    /**
     * A handler for rejected tasks that runs the rejected task
     * directly in the calling thread of the {@code execute} method,
     * unless the executor has been shut down, in which case the task
     * is discarded.
     */
    public static class CallerRunsPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code CallerRunsPolicy}.
         */
        public CallerRunsPolicy() { }

        /**
         * Executes task r in the caller's thread, unless the executor
         * has been shut down, in which case the task is discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }

    /**
     * A handler for rejected tasks that throws a
     * {@code RejectedExecutionException}.
     */
    public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

    /**
     * A handler for rejected tasks that silently discards the
     * rejected task.
     */
    public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardPolicy}.
         */
        public DiscardPolicy() { }

        /**
         * Does nothing, which has the effect of discarding task r.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }

    /**
     * A handler for rejected tasks that discards the oldest unhandled
     * request and then retries {@code execute}, unless the executor
     * is shut down, in which case the task is discarded.
     */
    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
         */
        public DiscardOldestPolicy() { }

        /**
         * Obtains and ignores the next task that the executor
         * would otherwise execute, if one is immediately available,
         * and then retries execution of task r, unless the executor
         * is shut down, in which case task r is instead discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }

}

四种拒绝策略的相关说明:

1、AbortPolicy:

默认。拒绝这个任务,并且抛出RejectedExecutionException异常。

2、DiscardPolicy:

队列满了,丢掉任务,不会抛出异常!

3、DiscardOldestPolicy

队列满了,尝试去和最早的竞争,也不会抛出异常!

抛弃最老任务策略,也就是说如果队列满了,就会将最早进入队列的任务抛弃,从队列中腾出空间,再尝试加入队列。因为队列是队尾进、队头出,队头元素是最老的,所以每次都是移除队头元素后再尝试入队。

4、CallerRunsPolicy

调用者执行策略。在新任务被添加到线程池时,如果添加失败,那么提交任务的线程会自己去执行该任务,不会使用线程池中的线程去执行新任务。

相关推荐
爬山算法3 分钟前
Hibernate(88)如何在负载测试中使用Hibernate?
java·后端·hibernate
自不量力的A同学7 分钟前
Solon AI v3.9 正式发布:全能 Skill 爆发
java·网络·人工智能
万岳科技系统开发18 分钟前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
独断万古他化22 分钟前
【Spring 原理】Bean 的作用域与生命周期
java·后端·spring
*小海豚*27 分钟前
在linux服务器上DNS正常,但是java应用调用第三方解析域名报错
java·linux·服务器
撩得Android一次心动43 分钟前
Android LiveData 全面解析:使用Java构建响应式UI【源码篇】
android·java·android jetpack·livedata
组合缺一1 小时前
Solon AI (Java) v3.9 正式发布:全能 Skill 爆发,Agent 协作更专业!仍然支持 java8!
java·人工智能·ai·llm·agent·solon·mcp
MSTcheng.1 小时前
【C++】C++11新特性(二)
java·开发语言·c++·c++11
愚者游世1 小时前
Delegating Constructor(委托构造函数)各版本异同
开发语言·c++·程序人生·面试·改行学it
一 乐1 小时前
校园二手交易|基于springboot + vue校园二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端