如何优雅地保证程序不退出?

首先提两个问题:

  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

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