Java完成工作单元,直到发出停止信号

Java完成工作单元,直到发出停止信号,java,signals,synchronized,atomicity,shutdown-hook,Java,Signals,Synchronized,Atomicity,Shutdown Hook,我有一些(Linux)C代码,我正在将其转换为Java。该代码有一个主循环,用于在每个环上检查来自操作系统的术语信号,否则会阻塞信号。这是因为它在循环中所做的每一个“功单元”都是完全完成的(不会被中间的信号中断) 事实证明,用Java实现这一点有些“有趣”。我已经提出了一些测试代码(如下所示),这些代码似乎有效,但我不确定它是否会一直有效,或者我是否只是在测试中“幸运” 所以,这就是我的问题:这是一个好的代码,还是只是偶尔能工作的代码? TL;DR:工作线程和关闭线程调用一个公共的同步方法 只要

我有一些(Linux)C代码,我正在将其转换为Java。该代码有一个主循环,用于在每个环上检查来自操作系统的术语信号,否则会阻塞信号。这是因为它在循环中所做的每一个“功单元”都是完全完成的(不会被中间的信号中断)

事实证明,用Java实现这一点有些“有趣”。我已经提出了一些测试代码(如下所示),这些代码似乎有效,但我不确定它是否会一直有效,或者我是否只是在测试中“幸运”

所以,这就是我的问题:这是一个好的代码,还是只是偶尔能工作的代码?

TL;DR:工作线程和关闭线程调用一个公共的同步方法


只要关闭钩子在您期望的所有情况下都运行(并完成),它就一定是好的。根据SIGTERM,它似乎与预期一样工作。如果您不需要使用信号处理程序显式捕获操作系统信号,我认为您不必担心。

所有可用的证据表明,如果您注册了一个ShutdownHook,那么它将在一个TERM或INT信号传递到JVM时启动,所有其他线程都将保持独立,直到ShutdownHook运行()方法退出(当任何仍在运行的方法将被终止时)

因此,这导致了一个更简单的解决方案,它避免了同步

public class AnotherTestShutdownHook {
    static int        a          = 0;           /* should end up 0 */
    static boolean    go         = true;        /* signaled to stop */
    static Thread     mainThread = Thread.currentThread();

    private static void trySleep ( int msecs ) {
        try { Thread.sleep(msecs); } catch (InterruptedException e) {}
    }

    private static void tryJoin ( Thread t ) {
        try { t.join(); } catch (InterruptedException e) {}
    }

    /*
     * this simulates a process that we want to do completely
     * or not at all.
     */
    private static void doitall () {
        System.out.println("start");
        ++a;
        trySleep(5000);
        System.out.println("end");
        --a;
    }

    /*
     * starts a thread to wait for a shutdown signal,
     * then does units of work until told to stop
     */
    public static void main(String[] args) {  
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("Shutdown coming...");
                go = false; 
                tryJoin(mainThread);        // wait for mainThread to exit
                System.out.println("Shutdown hook! " + a);
            }       
        }); 
        while (go) {
            doitall();
        }   
        System.out.println("goodbye");
    }
}

为什么你认为它不会每次都起作用?我没有发现任何缺陷,在一个退出信号上,如果JVM正常关闭或使用^C关闭,doitall()的工作应该完成。我想你已经阅读了Java文档。我在谷歌上搜索了很多,我找到了很多关于JNI和sun.misc.motled.carbody的话题,“你没有用Java的方式思考”等等,但我没有找到这种方法,所以我有点自我怀疑。谢谢你鼓励我重读这个问题——我认为这是最有用的答案——他想打断所有其他的线索,但这只是一个小小的飞跃,让它们很好地结束。
public class AnotherTestShutdownHook {
    static int        a          = 0;           /* should end up 0 */
    static boolean    go         = true;        /* signaled to stop */
    static Thread     mainThread = Thread.currentThread();

    private static void trySleep ( int msecs ) {
        try { Thread.sleep(msecs); } catch (InterruptedException e) {}
    }

    private static void tryJoin ( Thread t ) {
        try { t.join(); } catch (InterruptedException e) {}
    }

    /*
     * this simulates a process that we want to do completely
     * or not at all.
     */
    private static void doitall () {
        System.out.println("start");
        ++a;
        trySleep(5000);
        System.out.println("end");
        --a;
    }

    /*
     * starts a thread to wait for a shutdown signal,
     * then does units of work until told to stop
     */
    public static void main(String[] args) {  
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("Shutdown coming...");
                go = false; 
                tryJoin(mainThread);        // wait for mainThread to exit
                System.out.println("Shutdown hook! " + a);
            }       
        }); 
        while (go) {
            doitall();
        }   
        System.out.println("goodbye");
    }
}