SpringBoot 使用异步线程池方式如下

第一种

  1. 创建自定义线程池配置类,AsyncTaskExecutePool
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@EnableAsync
@Configuration
public class AsyncTaskExecutePool {

//核心线程池大小
private final int corePoolSize = 10;
//最大线程数
private final int maxPoolSize = 15;
//队列容量
private final int queueCapacity = 50;
//活跃时间/秒
private final int keepAliveSeconds = 60;

@Bean
public Executor myAsyncTaskPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程池大小
executor.setCorePoolSize(corePoolSize);
//最大线程数
executor.setMaxPoolSize(maxPoolSize);
//队列容量
executor.setQueueCapacity(queueCapacity);
//活跃时间
executor.setKeepAliveSeconds(keepAliveSeconds);
//设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
executor.setWaitForTasksToCompleteOnShutdown(true);
//线程名字前缀
executor.setThreadNamePrefix("my-async1--");
// setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
// CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
  1. 创建任务处理类AsyncTask
1
2
3
4
5
6
7
8
9
10
11
12
13
@Component
@Slf4j
public class AsyncTask {

/**
* myAsyncTaskPool 线程池的方法名,此处如果不写,会使用Spring默认的线程池
* @param i
*/
@Async("myAsyncTaskPool")
public void run(int i){
log.info("我是:" + i);
}
}
  1. 测试线程池AppTests
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@SpringBootTest
class AppTests {

@Autowired
private AsyncTask asyncTask;

@Test
void test(){
for (int i = 0; i < 100; i++) {
asyncTask.run(i);
}
}
}

运行查看效果

第二种

第二种方式是重写 spring 默认线程池,使用这种方式的好处是可以直接使用 @Async 注解

  1. 创建配置类AsyncTaskExecutePool1 并且实现AsyncConfigurer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Slf4j
@EnableAsync
@Configuration
public class AsyncTaskExecutePool1 implements AsyncConfigurer {

//核心线程池大小
private final int corePoolSize = 10;
//最大线程数
private final int maxPoolSize = 15;
//队列容量
private final int queueCapacity = 50;
//活跃时间/秒
private final int keepAliveSeconds = 60;

@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程池大小
executor.setCorePoolSize(corePoolSize);
//最大线程数
executor.setMaxPoolSize(maxPoolSize);
//队列容量
executor.setQueueCapacity(queueCapacity);
//活跃时间
executor.setKeepAliveSeconds(keepAliveSeconds);
//设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
executor.setWaitForTasksToCompleteOnShutdown(true);
//线程名字前缀
executor.setThreadNamePrefix("my-async-");
// setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
// CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}

/**
* 异步任务异常处理
* @return
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (throwable, method, objects) -> {
log.error("===="+throwable.getMessage()+"====", throwable);
log.error("exception method:"+method.getName());
};
}
}
  1. 修改AsyncTask 类,在类中加入方法run1
1
2
3
4
@Async
public void run1(int i){
log.info("我是:" + i);
}
  1. 测试,在AppTests 中加入方法test1
1
2
3
4
5
6
@Test
void test1(){
for (int i = 0; i < 100; i++) {
asyncTask.run1(i);
}
}

运行查看效果

注意

  1. 同类中调用带有@Async 的方法是不生效的
  2. 例子中的参数根据具体的需求修改

源码

本文源码:https://github.com/elunez/spring-boot-learn