SpringBoot 线程池的创建和 Async 注解

3 篇文章 0 订阅

线程池配置类

package com.memento.common.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author Memento
 * 1. 创建线程池后, 线程池中的线程数为 0;
 * 2. 任务过来之后开始创建线程执行;
 * 3. 当线程数达到 corePoolSize 后, 会把任务放到缓存队列 queueCapacity 中;
 * 4. 当缓存队列满了之后, 继续创建线程执行任务;
 * 5. 当线程数达到 maxPoolSize 后, 开始使用拒绝策略拒绝任务;
 */
@Configuration
@EnableAsync
public class ThreadPoolTaskConfig {
    /** 核心线程数(默认线程数), 默认值=1 **/
    private static final int CORE_POOL_SIZE = 20;
    /** 最大线程数, 默认值=2147483647 **/
    private static final int MAX_POOL_SIZE = 100;
    /** 缓冲队列大小, 默认值=2147483647 **/
    private static final int QUEUE_CAPACITY = 200;
    /** 允许线程空闲时间(单位: s), 默认值=60 **/
    private static final int KEEP_ALIVE_TIME = 10;
    /** 线程池名前缀 **/
    private static final String THREAD_NAME_PREFIX = "Async-Service-";

    @Bean("taskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(CORE_POOL_SIZE);
        executor.setMaxPoolSize(MAX_POOL_SIZE);
        executor.setQueueCapacity(QUEUE_CAPACITY);
        executor.setKeepAliveSeconds(KEEP_ALIVE_TIME);
        executor.setThreadNamePrefix(THREAD_NAME_PREFIX);

        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化
        executor.initialize();
        return executor;
    }
}

最大任务数=maxPoolSize+queueCapacity

拒绝策略:

  1. CallerRunsPolicy, 当任务数超过最大任务数后, 该策略表示后续任务直接执行;
  2. AbortPolicy, 当任务数超过最大任务数后, 该策略表示直接拒绝任务, 但是会抛出 RejectedExecutionException 给主线程;
  3. DiscardPolicy, 当任务数超过最大任务数后, 该策略表示直接忽略任务, 对主线程无任何影响;
  4. DiscardOldestPolicy, 当任务数超过最大任务数后, 该策略表示忽略最旧的任务, 并把后续的任务插入队列, 对主线程无任何影响;

Async 注解使用

@Async("taskExecutor")
public void sendMessage1() throws InterruptedException {
    logger.info("发送短信方法---- 1 执行开始");
    // 模拟耗时
    Thread.sleep(5000);
    logger.info("发送短信方法---- 1 执行结束");
}

@Async("taskExecutor") 指定使用自定义线程池 @Bean("taskExecutor");

注意事项

以下方式会使 @Async 失效:

  1. 异步方法用 static 修饰; (经验证, 现在的 @Async 标注的方法, 无法加 static 作为静态方法)
  2. 异步类没有使用 @Component 注解, 或其他注解, 导致 spring 无法扫描到异步类;
  3. 异步方法不能与被调用的异步方法在同一个类中; (核实正确)
  4. 类中需要使用 @Autowired@Resource 等注解自动注入, 不能手动 new 对象; (这里应该是指线程池配置类)
  5. 如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解 (经验证, 可以不在启动类中增加 @EnableAsync 注解)

参考资料

  1. SpringBoot线程池的创建、@Async配置步骤及注意事项
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

01码匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值