用法和介绍
功能描述
使用方法
代码示例
@EnableAsync@SpringBootApplicationpublic class StartApplication { public static void main(String[] args) { SpringApplication.run(StartApplication.class, args); }}@Servicepublic class AsyncService { /** * 使用默认线程池 */ @Async public void say(){ } /** * 指定线程池名称 */ @Async(“getAsyncExecutor”) public void eat(){ }}@Configurationpublic class MyAsyncConfiguration { //核心线程数 private static final int CORE_POOL_SIZE = 5; //最大线程数 private static final int MAX_POOL_SIZE = 15; //队列大小 private static final int QUEUE_CAPACITY = 100; //线程池中的线程的名称前缀 private static final String THREAD_NAME = “MyThread-“; @Bean public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //配置核心线程数 executor.setCorePoolSize(CORE_POOL_SIZE); //配置最大线程数 executor.setMaxPoolSize(MAX_POOL_SIZE); //配置队列大小 executor.setQueueCapacity(QUEUE_CAPACITY); //配置线程池中的线程的名称前缀 executor.setThreadNamePrefix(THREAD_NAME); //配置线程池拒绝策略,设置为CallerRunsPolicy,当线程和队列都满了,由发起线程的主线程自己执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; }}
已实现的TaskExecutor线程池
- SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。
- SyncTaskExecutor:这个类没有实现异步调用,只是一个同步操作,只适用于不需要多线程的地方。
- ConcurrentTaskExecutor:Executor的适配类,不推荐使用。如果ThreadPoolTaskExecutor不满足要求时,才用考虑使用这个类 。
- SimpleThreadPoolTaskExecutor:是Quartz的SimpleThreadPool的类。线程池同时被quartz和非quartz使用,才需要使用此类。
- ThreadPoolTaskExecutor :最常使用,推荐。 其实质是对java.util.concurrent.ThreadPoolExecutor的包装。
为什么说一定要指定线程池名称
@Async依赖线程池,当我们未指定线程池@Async会如何选择呢?
1. 当系统未配置任何线程池时
SpringBoot会默认添加一个coreSize=8的 ThreadPoolTaskExecutor 无界线程池,名称applicationTaskExecutor。
2. 当只配置了一个TaskExecutor线程池时
使用此线程池
3. 当只配置了一个线程池,但不是TaskExecutor线程池时
使用 SimpleAsyncTaskExecutor 线和池
4. 当有多个TaskExecutor线程池时
默认使用 SimpleAsyncTaskExecutor 线程池,如果指定就使用指定的线程池(即使不是TaskExecutor类型的线程池也可以)
注意:SimpleAsyncTaskExecutor 不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。强烈建议开发时指定线程池的名称,避免创建多个TaskExecutor实例后,使用 SimpleAsyncTaskExecutor 线和池的情况发生