欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring boot 异步@Async使用线程池

程序员文章站 2022-05-01 14:18:48
...

1.业务中遇到一些场景: 做一个告警策略的生成的逻辑,需要对用户定义的告警信息进行循环判断,业务要求1000条要在15秒内处理完成.通过日志打印单条生成耗时0.08秒左右,粗略估算,单线程1秒能处理10条,如果有10个线程同时处理的话,那么理想状态10秒内是可以完成的;

在启动类中设置初始化线程,启动类 中使用@EnableAsync 开启异步支持

 /** Set the ThreadPoolExecutor's core pool size. */
    private int corePoolSize = 10;
    /** Set the ThreadPoolExecutor's maximum pool size. */
    private int maxPoolSize = 20;
    /** Set the capacity for the ThreadPoolExecutor's BlockingQueue. */
    private int queueCapacity = 200;

    @Bean ("threadPoolTaskExecutor")
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix("AlarmExecutor-");
        executor.setKeepAliveSeconds(60);
        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
  /**
     * 告警判断 与写入,通知逻辑
     *
     * @param alarmMessageInsertList
     * @param alarmRevertMap
     * @param updateCountList
     */
    private void generateKpiAlarm(List<AlarmInfo> alarmMessageInsertList, Map<String, Object> alarmRevertMap,
            List<AlarmInfo> updateCountList) {
        // 3.0版本改造,将策略与资源一起查出
        List<AlarmStrategyVo> alarmStrategies = alarmStMapper.selectAllAndSource();
        if (NullUtil.isNull(alarmStrategies)) {
            log.info("未查询到有效的告警策略!");
            return;
        }
        for (AlarmStrategyVo alarmStrategy : alarmStrategies) {
            //异步处理 单条判断->写入->通知
            alarmGenerator.getAlarmNoticeMap(alarmStrategy);
        }
    @Async("threadPoolTaskExecutor")
    @Override
    public void getAlarmNoticeMap(AlarmStrategyVo alarmStrategy) {
      //业务逻辑
    }

for 循环里面的方法做了异步处理

这里遇到两个坑

1.初始化线程池的bean 一直失败 ,尝试新建类,将初始化线程池单独一个类,重启idea,重新编译,甚至新建一个项目都是可以正常使用的,然而在自己的项目无卵用

spring boot 异步@Async使用线程池

而正确的打印应该是 Initialzing  ExeutorService

spring boot 异步@Async使用线程池

当天就是无论怎么都加载不进来,搞了一下午,关机下班,第二天一来 ,重新尝试,竟然ok了,判断可能是项目哪里冲突了,缓存原因,真实原因还仍未知,郁闷

2.第二个问题是for循环里的异步不生效,日志显示还是使用同步去跑的,异步没有生效

解决方法: 一开始for循环中为类中调用,查阅资料后将for循环里的方法单独做个类,异步才生效