springboot 优雅关闭
应用:停机升级服务时, 若仍有线程运行,可等待一段时间后关闭应用;若线程未执行完成关闭应用,输出相应提示
********************************
示例
*********************
config 层
GracefulShutDown
@Component
public class GracefulShutDown implements TomcatConnectorCustomizer,
ApplicationListener<ContextClosedEvent> {
private Logger logger= LoggerFactory.getLogger(GracefulShutDown.class);
private Connector connector;
@Override
public void customize(Connector connector) {
this.connector=connector;
}
@Override
public void onApplicationEvent(ContextClosedEvent contextClosedEvent) { //容器关闭之前调用
this.connector.pause();
Executor executor=this.connector.getProtocolHandler().getExecutor();
if (executor instanceof ThreadPoolExecutor){
ThreadPoolExecutor threadPoolExecutor=(ThreadPoolExecutor) executor;
threadPoolExecutor.shutdown(); //若无线程运行,立即关闭线程池;若有线程运行则等待
try {
if (!threadPoolExecutor.awaitTermination(10, TimeUnit.SECONDS)){
//等待10s,为false表示线程池没有关闭,随后强制关闭,此时正在执行的任务中断,只执行了一部分,控制台输出warn日志
logger.warn("10秒后线程未关闭,将强制关闭");
}else {
System.out.println("线程池已关闭:"+ LocalDateTime.now());
} //为true,线程池已经关闭,任务执行完成
}catch (Exception e){
e.printStackTrace();
}
}
}
}
*********************
controller 层
HelloController
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
try{
Thread.sleep(2000);
}catch (Exception e){
System.out.println(e.getMessage());
}
return "hello world";
}
@RequestMapping("/hello2")
public String hello2(){
try{
Thread.sleep(20000);
}catch (Exception e){
System.out.println(e.getMessage());
}
return "hello world";
}
}
**************************
使用测试
/hello
说明:ctrl+c时任务执行结束,线程池立即关闭
/hello2
说明:ctrl+c时任务没有执行结束,线程池没有立即关闭;等待10s后线程池强制关闭,任务没有执行完成,无返回结果