spring boot 异步@Async使用线程池

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,重新编译,甚至新建一个项目都是可以正常使用的,然而在自己的项目无卵用

而正确的打印应该是 Initialzing  ExeutorService

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

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

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

3.不乱用注解,今天一个同事在不该使用多线程地方,乱用@Async  还使用了2秒一次的定时去跑任务,导致了很多bug,比如添加重复

原因:需要处理的常量池,多个线程在短时间内竞争,有的线程能拿到,有的线程拿不到资源,这里程序不会报错,但是业务上可能会有其他情况出现,导致后面的判断失误,这是没必要的.一个线程去处理就足够的,举个例子

线程10就没能成功取消任务,因为线程3已经获取到并提前取消了,后面的自然会有其他判断分歧,极短的时间循环,拿到的都数据也不是最新数据库修改成功的数据,可能3个线程同时获取到老数据,所以这三个的逻辑会同时添加成功,会有重复添加的情况.所以要考虑业务场景需不需要使用,而不是为了用而用;

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值