如何優雅地保證程序不退出?

首先提兩個問題:

  1. springboot應用程序只在main方法中調用SpringApplication.run(xx),程序就運行起來了,他爲什麼能保持住不退出?
  2. 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章