Springboot与线程池整合(异步处理)

一、线程池基本配置

1.1 配置文件

#springboot线程池配置
task:
  pool:
    corePoolSize: 10
    maxPoolSize: 20
    keepAliveSeconds: 300
    queueCapacity: 50

1.2 基本配置类

@Data
@Component
@ConfigurationProperties(prefix = "task.pool")
public class TaskThreadPoolConfig {
  /** 核心线程数 */
  private int corePoolSize;
  /** 最大线程数 */
  private int maxPoolSize;
  /** 线程空闲时间 */
  private int keepAliveSeconds;
  /** 任务队列容量(阻塞队列) */
  private int queueCapacity;
}

二、线程池配置

2.1 重写默认线程池

@Slf4j
@Component
@EnableAsync
public class OverrideDefaultThreadPoolConfig implements AsyncConfigurer {
  @Autowired private TaskThreadPoolConfig config;

  @Override
  public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    // 核心线程池大小
    executor.setCorePoolSize(config.getCorePoolSize());
    // 最大线程数
    executor.setMaxPoolSize(config.getMaxPoolSize());
    // 队列容量
    executor.setQueueCapacity(config.getQueueCapacity());
    // 活跃时间
    executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
    // 线程名字前缀
    executor.setThreadNamePrefix("default-thread-");
    /*
     当poolSize已达到maxPoolSize,如何处理新任务(是拒绝还是交由其它线程处理)
     CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
    */
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    executor.initialize();
    return executor;
  }

  /**
   * 异步任务中异常处理
   *
   * @return
   */
  @Override
  public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return (ex, method, params) -> {
      log.error("==========================" + ex.getMessage() + "=======================", ex);
      log.error("exception method:" + method.getName());
    };
  }

2.2 创建自定义线程池

@Configuration
@EnableAsync
public class CustomizeThreadPoolConfig {

  @Autowired private TaskThreadPoolConfig config;

  @Bean("customizeThreadPool")
  public Executor doConfigCustomizeThreadPool() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    // 核心线程池大小
    executor.setCorePoolSize(config.getCorePoolSize());
    // 最大线程数
    executor.setMaxPoolSize(config.getMaxPoolSize());
    // 队列容量
    executor.setQueueCapacity(config.getQueueCapacity());
    // 活跃时间
    executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
    // 线程名字前缀
    executor.setThreadNamePrefix("customize-thread-");
    /*
     当poolSize已达到maxPoolSize,如何处理新任务(是拒绝还是交由其它线程处理)
     CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
    */
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    executor.initialize();
    return executor;
  }
}

三、使用springboot默认的线程池

3.1 通过@Async注解调用

  • 第一步:在Application启动类上面加上@EnableAsync
@SpringBootApplication
@EnableAsync
public class ThreadpoolApplication {
    public static void main(String[] args) {
        SpringApplication.run(ThreadpoolApplication.class, args);
    }
}
  • 第二步:在需要异步执行的方法上加上@Async注解
@Service
public class AsyncTest {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    
	// 使用默认线程池
	@Async
    public void hello(String name){
    	//这里使用logger 方便查看执行的线程是什么
        logger.info("默认线程池:异步线程启动 started."+name);  
    }
	
	// 使用自定义线程池
	@Async("customizeThreadPool")
    public void hi(String name){
    	//这里使用logger 方便查看执行的线程是什么
        logger.info("自定义线程池:异步线程启动 started."+name);  
    }
}
  • 第三步:测试类进行测试验证
    @Autowired
    AsyncTest asyncTest;
    @Test
    void contextLoads() throws InterruptedException {
        asyncTest.hello("afsasfasf");
        //一定要休眠 不然主线程关闭了,子线程还没有启动
        Thread.sleep(1000);
    }

3.2 直接调用ThreadPoolTaskExecutor

直接注入ThreadPoolTaskExecutor

@SpringBootTest
class ThreadPoolApplicationTests {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    AsyncTest asyncTest;
    @Autowired private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Test
    void asyncTest0() throws InterruptedException {
        asyncTest.hello("async注解创建");
        threadPoolTaskExecutor.submit(new Thread(()->{
            logger.info("threadPoolTaskExecutor 创建线程");
        }));
        //一定要休眠 不然主线程关闭了,子线程还没有启动
        Thread.sleep(1000);
    }
}

以上,请参考,谢谢!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值