首先提兩個問題:
- 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