首先提两个问题:
- springboot应用程序只在main方法中调用SpringApplication.run(xx),程序就运行起来了,他为什么能保持住不退出?
- quartz程序为什么能一直运行不退出?
我们为了让程序保持不退出,一般使用Thread.sleep方法,或者使用一个while无限循环,但是总感觉不太优雅。参考springboot和tomcat的源码写了一个小工具,可以优雅地实现程序保持住不退出。
package top.jfunc.common.thread;
import java.util.concurrent.TimeUnit;
/**
* 使程序不退出,保证至少一个前台进程
* @see https://dubbo.apache.org/zh-cn/blog/spring-boot-dubbo-start-stop-analysis.html
* @author xiongshiyan at 2019/10/16 , contact me with email [email protected] or phone 15208384257
*/
public class HoldProcessor {
private volatile boolean stopAwait = false;
/**
* Thread that currently is inside our await() method.
*/
private volatile Thread awaitThread = null;
/**
* 开始等待
*/
public void startAwait(){
Thread awaitThread = new Thread(this::await,"hold-process-thread");
awaitThread.setContextClassLoader(getClass().getClassLoader());
//这一步很关键,保证至少一个前台进程
awaitThread.setDaemon(false);
awaitThread.start();
}
/**
* 停止等待,退出程序,一般放在shutdown hook中执行
* @see Runtime#addShutdownHook(Thread)
*/
public void stopAwait() {
//此变量
stopAwait=true;
Thread t = awaitThread;
if (null != t) {
t.interrupt();
try {
t.join(1000);
} catch (InterruptedException e) {
// Ignored
}
}
}
private void await(){
try {
awaitThread = Thread.currentThread();
while(!stopAwait) {
try {
TimeUnit.SECONDS.sleep(10);
} catch( InterruptedException ex ) {
// continue and check the flag
}
}
} finally {
awaitThread = null;
}
}
}
示例使用方法:
System.out.println("程序开始");
HoldProcessor holdProcessor = new HoldProcessor();
System.out.println("开始等待");
holdProcessor.startAwait();
System.out.println("添加shutdown hook");
Runtime.getRuntime().addShutdownHook(new Thread(()->{
System.out.println("收到kill 信号,停止程序");
holdProcessor.stopAwait();
}));
参考:https://dubbo.apache.org/zh-cn/blog/spring-boot-dubbo-start-stop-analysis.html