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

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

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

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

相关推荐
前端Hardy42 分钟前
面试官:JS数组的常用方法有哪些?这篇总结让你面试稳了!
javascript·面试
日月云棠1 小时前
各版本JDK对比:JDK 25 特性详解
java
牛奶1 小时前
React 底层原理 & 新特性
前端·react.js·面试
牛奶2 小时前
ts随笔:面向对象与高级类型
前端·面试·typescript
牛奶2 小时前
React 基础理论 & API 使用
前端·react.js·面试
SuperEugene2 小时前
从 Vue2 到 Vue3:语法差异与迁移时最容易懵的点
前端·vue.js·面试
用户8307196840822 小时前
Spring Boot 项目中日期处理的最佳实践
java·spring boot
JavaGuide3 小时前
Claude Opus 4.6 真的用不起了!我换成了国产 M2.5,实测真香!!
java·spring·ai·claude code
IT探险家3 小时前
Java 基本数据类型:8 种原始类型 + 数组 + 6 个新手必踩的坑
java
花花无缺3 小时前
搞懂new 关键字(构造函数)和 .builder() 模式(建造者模式)创建对象
java