开启异步
zeal 2020-08-20
# 配置异步线程池
/**
* 线程池配置类.
*
* @author zhanglei
* @date 2018/10/25 11:29 AM
*/
@Slf4j
@Configuration
public class AsyncTaskExecutePool implements AsyncConfigurer {
/**
* IO密集型任务 = 一般为2*CPU核心数(常出现于线程中:数据库数据交互、文件上传下载、网络数据传输等等)
* CPU密集型任务 = 一般为CPU核心数+1(常出现于线程中:复杂算法)
* 混合型任务 = 视机器配置和复杂度自测而定.
*/
private static final int corePoolSize = Runtime.getRuntime().availableProcessors();
/**
* 最大线程数.
*/
private static final int maxPoolSize = 2 * corePoolSize;
/**
* 队列容量.
*/
private static final int queueCapacity = 1000;
/**
* 线程活跃时间.
*/
private static final int keepAliveSeconds = 60;
/**
* 线程名称前缀.
*/
private static final String threadNamePrefix = "zealsay-";
/**
* corePoolSize用于指定核心线程数量
* maximumPoolSize指定最大线程数
* keepAliveTime和TimeUnit指定线程空闲后的最大存活时间
* workQueue则是线程池的缓冲队列,还未执行的线程会在队列中等待
* 监控队列长度,确保队列有界
* 不当的线程池大小会使得处理速度变慢,稳定性下降,并且导致内存泄露。如果配置的线程过少,则队列会持续变大,消耗过多内存。
* 而过多的线程又会 由于频繁的上下文切换导致整个系统的速度变缓——殊途而同归。队列的长度至关重要,它必须得是有界的,这样如果线程池不堪重负了它可以暂时拒绝掉新的请求。
* ExecutorService 默认的实现是一个无界的 LinkedBlockingQueue.
*
* @author zhanglei
* @date 2018/10/25 1:59 PM
*/
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数.
executor.setCorePoolSize(corePoolSize);
// 设置最大线程数.
executor.setMaxPoolSize(maxPoolSize);
// 设置队列容量.
executor.setQueueCapacity(queueCapacity);
// 设置线程活跃时间(秒).
executor.setKeepAliveSeconds(keepAliveSeconds);
// 设置默认线程名称.
executor.setThreadNamePrefix(threadNamePrefix);
// 设置拒绝策略.
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池.
executor.setWaitForTasksToCompleteOnShutdown(true);
//初始化
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
// 异步任务中异常处理
return (arg0, arg1, arg2) -> log.error("when execute '{}' occurred an exception ", arg1.getName());
}
}
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# 开启注解
在需要异步执行的方法上开启注解
@Async
1
# 同步返回
如果你的某一个方法里面有多个异步调用,在数据返回时候期望能等待所有线程都执行完再同步返回,那么可能需要如下改造
- 将方法定义成
Future
类型. - 返回
AsyncResult
示例如下:
@Async
public Future<List<User>> getList() {
List<User> list = userService
.getList();
return new AsyncResult<>(list);
}
1
2
3
4
5
6
7
2
3
4
5
6
7