如何在Java中优雅地处理SIGTERM信号?

7
假设我们有一个用Java编写的如此简单的守护程序:
public class Hellow {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        while(true) {
            // 1. do
            // 2. some
            // 3. important
            // 4. job
            // 5. sleep
        }

    }
}

我们使用start-stop-daemon将其守护进程化,默认情况下,在--stop时发送SIGTERM(TERM)信号。

假设当前执行的步骤是#2。此时,我们正在发送TERM信号。

执行会立即终止。

我发现可以使用addShutdownHook()处理信号事件,但问题在于它仍然会中断当前执行并将控制权传递给处理程序:

public class Hellow {
    private static boolean shutdownFlag = false;
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        registerShutdownHook();

        try {
            doProcessing();
        } catch (InterruptedException ex) {
            System.out.println(ex);
        }
    }

    static private void doProcessing() throws InterruptedException {
        int i = 0;
        while(shutdownFlag == false) {
            i++;
            System.out.println("i:" + i);
            if(i == 5) {
                System.out.println("i is 5");
                System.exit(1); // for testing
            }

            System.out.println("Hello"); // It doesn't print after System.exit(1);

            Thread.sleep(1000);
        }
    }

    static public void setShutdownProcess() {
        shutdownFlag = true;
    }

    private static void registerShutdownHook() {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                System.out.println("Tralala");
                Hellow.setShutdownProcess();
            }
        });
    }
}

所以,我的问题是 - 是否可能不中断当前执行,而是在一个分离的线程中处理 TERM 信号 (?),这样我就可以设置 shutdown_flag = True,以便主循环中的循环有机会平稳地停止?
2个回答

12

我重新编写了registerShutdownHook()方法,现在它按照我想要的方式工作了。

private static void registerShutdownHook() {
    final Thread mainThread = Thread.currentThread();
    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
            try {
                System.out.println("Tralala");
                Hellow.setShutdownProcess();
                mainThread.join();
            } catch (InterruptedException ex) {
                System.out.println(ex);
            }

        }
    });  
}

0

您可以使用SignalHandler。请查看此示例:https://dumpz.org/2707213/

它将捕获INTERRUPTED信号并取消设置operating标志,从而允许应用程序优雅地关闭。

enter image description here


是的,你的解决方案可以工作,但在编译时编译器会发誓 SignalHandler 在未来不起作用。我找到了另一个解决方案,但还是谢谢你。 - Islomkhodja Hamidullakhodjaev
@IslomkhodjaHamidullakhodjaev 你能分享一下你的解决方案吗?敬祝好意。 - Jorge Lavín

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接