清明加班三天, 进度堪忧, 反而学会了@Async的用法
@Async注解
该注解从Spring 3版本开始提供,在Springboot中只需要配合@EnableAsync注解就可以开启异步, Spring中默
认创建SimpleAsyncTaskExecutor, 使用了@Async标识一个方法为异步方法,通过
SimpleAsyncTaskExecutor去执行,但不推荐使用这个默认线程池~~~
随口一提(小概念~):
@EnableXXX这类注解在SpringBoot中基本都是开启某些功能的开关
同步: 当调用方法等动作发生时, 必须等到动作执行完成,并产生结果后才可以进行下一个动作~
异步: 当调用方法等动作发生时,可以在该动作执行完成前, 同时进行下一个动作, 最终都执行完成~
回到正文, 查看Spring源码关于@Async的默认调用规则,会优先查询源码中实现AsyncConfigurer这个接口
的类,实现这个接口的类为AsyncConfigurerSupport。 由于AsyncConfigurer的默认线程池在源码中为
空,Spring通过 beanFactory.getBean(TaskExecutor.class) 先查看是否有线程池,未配置时,通
过 beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class) ,来查询是否存在默认名称为
TaskExecutor的线程池。上面提到SimpleAsyncTaskExecutor线程池, 便是代码中没有配置自定义的线程池
时默认创建的。
Spring支持的线程池种类还有多种,它们都继承于TaskExecutor,本质上都是Java.util.concurrent.Executor
其他线程池没有具体使用过, 就不管啦~~~
说一下默认线程池的弊端在于,容易造成OOM问题,原因是程序每次请求线程资源,
SimpleAsyncTaskExecutor线程池都会创建一个新的线程,不会复用空闲的线程。虽然
SimpleAsyncTaskExecutor线程池也提供了限流机制,通过concurrencyLimit属性来控制开关,当
concurrencyLimit>=0时开启限流机制,默认关闭限流机制即concurrencyLimit=-1,当关闭情况下,会不断
创建新的线程来处理任务。基于默认配置,SimpleAsyncTaskExecutor并不是严格意义的线程池,达不到线
程复用的功能。