springboot线程池优雅关闭

在我们停止springboot项目时,我们希望线程池中的任务能够继续执行完再完全停掉服务。一般有两种做法:

线程池配置参数

在spring应用中,如果需要
停止服务,而线程池没有优雅的关闭,就会造成线程池中的任务被强行停止,导致部分任务执行失败。我们只需要在配置线程池时增加两个参数即可:

  • waitForTasksToCompleteOnShutdown
  • awaitTerminationSeconds 具体代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
@Bean
public ThreadPoolTaskExecutor treadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(10);
executor.setKeepAliveSeconds(60);
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(30);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}

使用ApplicationListener监听关闭事件

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
@Component
public class MyContextClosedHandler implements ApplicationListener<ContextClosedEvent>{
@Autowired
private ThreadPoolTaskExecutor executor;

@Override
public void onApplicationEvent(ContextClosedEvent event) {
shutdownAndAwaitTermination(executor.getThreadPoolExecutor());
}

private void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(30, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(30, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
}