[线程池] 项目中如何配置线程池

一、配置文件application.yml

# 线程池配置
thread:
  pool:
    executor:
      config:
        core-pool-size: 20
        max-pool-size: 50
        keep-alive-time: 5000
        block-queue-size: 5000
        policy: CallerRunsPolicy

二、线程池配置属性类

@Data
// 读取配置文件thread.pool.executor.config下的属性
// 忽略无法映射的属性
@ConfigurationProperties(prefix = "thread.pool.executor.config", ignoreInvalidFields = true)
public class ThreadPoolConfigProperties {

    /** 核心线程数 */
    private Integer corePoolSize = 20;
    /** 最大线程数 */
    private Integer maxPoolSize = 200;
    /** 最大等待时间 */
    private Long keepAliveTime = 10L;
    /** 最大队列数 */
    private Integer blockQueueSize = 5000;
    /*
     * AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
     * DiscardPolicy:直接丢弃任务,但是不会抛出异常
     * DiscardOldestPolicy:将最早进入队列的任务删除,之后再尝试加入队列的任务被拒绝
     * CallerRunsPolicy:如果任务添加线程池失败,那么主线程自己执行该任务
     * */
    private String policy = "AbortPolicy";

}

三、线程池配置类

@Slf4j
// 开启spring异步方法的支持,使@Async注解的方法运行在异步模式下
@EnableAsync
// 表示这个类是一个Spring配置类,用于定义配置信息和Bean
@Configuration
// 启动对ThreadPoolConfigProperties类的配置属性的支持
@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
public class ThreadPoolConfig {

    // 标记该方法是bean工厂方法,返回的对象交给spring容器管理
    @Bean
    // 条件创造bean:容器中没有ThreadPoolExecutor类型的bean时才进行创建
    @ConditionalOnMissingBean(ThreadPoolExecutor.class)
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties properties) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        // 实例化策略
        RejectedExecutionHandler handler;
        switch (properties.getPolicy()){
            case "AbortPolicy":
                handler = new ThreadPoolExecutor.AbortPolicy();
                break;
            case "DiscardPolicy":
                handler = new ThreadPoolExecutor.DiscardPolicy();
                break;
            case "DiscardOldestPolicy":
                handler = new ThreadPoolExecutor.DiscardOldestPolicy();
                break;
            case "CallerRunsPolicy":
                handler = new ThreadPoolExecutor.CallerRunsPolicy();
                break;
            default:
                handler = new ThreadPoolExecutor.AbortPolicy();
                break;
        }
        // 创建线程池
        return new ThreadPoolExecutor(properties.getCorePoolSize(),
                properties.getMaxPoolSize(),
                properties.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(properties.getBlockQueueSize()),
                Executors.defaultThreadFactory(),
                handler);
    }

}

四、线程池知识点回顾

1. ThreadPoolExecutor参数

下面是ThreadPoolExecutor类的一个构造方法:

/**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

根据如上构造方法,在new一个ThreadPoolExecutor时需要传入如下参数 

return new ThreadPoolExecutor(properties.getCorePoolSize(),
                properties.getMaxPoolSize(),
                properties.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(properties.getBlockQueueSize()),
                Executors.defaultThreadFactory(),
                handler);

(1)核心线程数:corePoolSize

任务队列未达到队列容量时,最大可以同时运行的线程数量为corePoolSize。

(2)最大线程数:maxPoolSize

任务队列已满,此时可同时运行的线程数量变为maxPoolSize。

(3)等待时间keepAliveTime

线程池中的线程数量大于corePoolSize,如果没有新任务提交,核心线程外的线程不会立刻销毁,会等待keepAliveTime再被回收销毁。

(4)参数的时间单位:unit

一般是TimeUnit.SECOND

(5)阻塞队列:workQueue

(6)拒绝策略:handler

2. 线程池处理任务流程

结合上述参数,线程池处理任务的流程可以这样描述。

  1. 提交任务,判断核心线程池是否已满,如果没有满(当前线程数 < corePoolSize),则创建线程
  2. 如果核心线程池已满,但没达到最大线程数(corePoolSize <= 当前线程数 < maxPoolSize),则把该任务放到阻塞队列里等待执行
  3. 如果阻塞队列已满,但当前线程数 < maxPoolSize,则新建一个线程来执行任务。
  4. 如果当前线程数 >= maxPoolSize,那么会根据拒绝测觉拒绝提交的任务。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值