应用优雅关闭
# 优雅关闭
- Java中:通过Runtime.getRuntime().addShutdownHook()注册事件,当虚拟机关闭的前调用该方法的具体逻辑进行善后;
- Spring中:执行了ApplicationContext 的close之后,只要我们Bean配置了destroy策略,那Spring在关闭之前也会先执行我们的已实现好的destroy方法;
- 线程池中:shutdown比shutdownNow更优雅;
# 动态线程池优雅关闭
非Spring管理下的ThreadPoolTaskExecutor,把自己创建出来的线程池在Spring关闭的时候,进行优雅shutdown;
public class ThreadPoolExecutorShutdownDefinition implements ApplicationListener<ContextClosedEvent> {
/**
* 线程中的任务在接收到应用关闭信号量后最多等待多久就强制终止,其实就是给剩余任务预留的时间, 到时间后线程池必须销毁
*/
private static final long AWAIT_TERMINATION = 20;
/**
* awaitTermination的单位
*/
private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
private final List<ExecutorService> POOLS = Collections.synchronizedList(new ArrayList<>(12));
public void registryExecutor(ExecutorService executor) {
POOLS.add(executor);
}
@Override
public void onApplicationEvent(ContextClosedEvent event) {
if (CollectionUtils.isEmpty(POOLS)) {
return;
}
for (ExecutorService pool : POOLS) {
pool.shutdown();
try {
if (!pool.awaitTermination(AWAIT_TERMINATION, TIME_UNIT)) {
log.warn("Timed out while waiting for executor [{}] to terminate", pool);
}
} catch (InterruptedException ex) {
log.warn("Timed out while waiting for executor [{}] to terminate", pool);
Thread.currentThread().interrupt();
}
}
}
}
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
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
Spring封装过的ThreadPoolTaskExecutor,默认会优雅关闭,其实现了DisposableBean接口;