@Async @Scheduled的并发问题

本文探讨了Spring中@Scheduled定时任务与@Async异步执行器的并发问题,由于默认线程池资源不足,导致定时任务无法按时执行。问题源于spring-kafka的并发占用。分析了@EnableAsync的配置和线程池选取过程,包括AsyncAnnotationBeanPostProcessor、AsyncConfigurationSelector等。解决方法是为@Async和@Scheduled配置独立的线程池。
摘要由CSDN通过智能技术生成

问题场景:系统中@Scheduled设置的定时任务每两分钟执行一次,某一天上线了后发现@Scheduled不按时执行,经过排查发现是Spring内部某些内容共用了默认线程池,导致线程池资源不够而抢占资源导致。当时上线的是Kafka内容,引用了spring-kafka,经查发现其使用的线程池和@Scheduled是相同的默认线程池所以出现的问题,Kafka的大量并发持续占满线程池,导致定时任务抢占不到。


下面是对@Async的源码进行分析为例,分析下线程池的创建过程。对源码不感兴趣的,可以跳到最后看解决这个问题的方法代码。

源码分析过程

@EnableAsync 开启spring异步执行器,需要联合@Configuration注解一起使用
@Async 该注解可以标记一个异步执行的方法,也可以用来标注,表示类中的所有方法都是异步执行的。

@Async

返回值:void或AsyncResult或CompletableFuture
可以自己指定执行器的beanName: @Async(“xxxExecutor”)

*注意:@Async如果A类的A.a()方法调用同类的`@Async A.b()`方法异,会变成同步,因为底层实现是代理对注解扫描实现的,A.a()方法上没有注解,没有生成相应的代理类*

@EnableAsync

直接看源码注释,解释的很清楚,重要的内容有下面这些(其它点在另一篇详细解析中介绍)

  1. 搭配@Configuration一起使用
  2. 默认Spring会寻找已经定义的线程池,已定义的org.springframework.core.task.TaskExecutor实例或名称为taskExecutor的实例,如果都没有则会用org.springframework.core.task.SimpleAsyncTaskExecutor。 默认异步的异常只会打印日志
  3. 想自定义线程池或者异常捕获可以通过实现AsyncConfigurer来实现,如下
@Configuration
@EnableAsync
public class AppConfig implements AsyncConfigurer {
   
    @Override
    public Executor getAsyncExecutor() {
   
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(7);
        executor.setMaxPoolSize(42);
        executor.setQueueCapacity(11);
        executor.setThreadNamePrefix("MyExecutor-");
        executor.initialize();
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
   
        return new MyAsyncUncaughtExceptionHandler();
    }
}

@EnbaleAsync的属性annotation

定义需要被扫描的注解,默认的Spring的@Async和EJB的@javax.ejb.Asynchronous注解会被扫描,用户可以通过这个属性设置自定义的注解来被扫描为异步类或方法

@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
   
    Class<? extends Annotation> annotation() default Annotation.class;
    ... ...
}

如果你了解SpringBoot的自动装配原理,就知道看这类源码一眼看到就是@Import(AsyncConfigurationSelector.class)

AsyncConfigurationSelector

@Override
@Nullable
public String[] selectImports(AdviceMode adviceMode) 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱清清

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

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

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

打赏作者

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

抵扣说明:

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

余额充值