8

我正在尝试让一个关闭挂钩在我的 ubuntu 服务器上工作,但是我似乎遇到了多个线程的问题。使用基本的 ShutdownHook,当我使用 杀死进程时,以下代码确实有效kill <PID>,这意味着关闭行为被激活。

public static void main(String[] args) {
    ShutdownHook shutDown = new ShutdownHook();
    shutDown.attachShutDownHook();

    while(true){}
}

但是,带有附加线程的相同代码不会

public static void main(String[] args) {
    ShutdownHook shutDown = new ShutdownHook();
    shutDown.attachShutDownHook();

    (new Thread() {
        public void run() {
            while ( true ) {}
        }
    }).start();

    while(true){}
}

有任何想法吗?

class ShutdownHook {

    ShutdownHook() {
    }

    public void attachShutDownHook() {

            Runtime.getRuntime().addShutdownHook(new Thread() {
                    @Override
                    public void run() {
                            System.out.println("Shut down hook activating");
                    }
            });
            System.out.println("Shut Down Hook Attached.");

    }
}
4

3 回答 3

3

当仍有非守护线程在运行时,JVM 不会退出。尝试调用setDaemon(true)您的新线程。

于 2012-10-31T13:22:46.010 回答
1

以我自己的项目为例;

我的核心类产生了一大堆工作线程,工作人员运行必须完成的事务。

在我的核心课程中;

Runtime.getRuntime().addShutdownHook(new ShutdownCleanup());

看起来像;

public final class ShutdownCleanup extends Thread() {
    public void run() {
        log("waiting for worker threads to finish...");
        while(WorkerThread.transactionInProgress()) {
            Thread.sleep(1000);
        }
        //close various sockets and resources
    }
}

在我点击Ctrl+C终端的那一刻,log消息出现了。所以关闭钩子立即激活,它不是在程序准备好死亡时运行的东西,而是在收到关闭或终止请求后立即运行。

出于这个原因,我相信其他人所说的关闭钩子永远不会被调用,而仍然有一个线程活着是错误的。无论如何,只有在一切都死了之后才激活的关闭挂钩有什么意义?

可能是您正在使用硬杀,例如 -9。您是否尝试过使用Ctrl+Cor正常关机SIGINT

于 2012-10-31T13:43:16.803 回答
0

java.lang.Runtime.addShutdownHook( Thread )注册一个新的虚拟机关闭钩子:

Java 虚拟机关闭以响应两种事件:

  • 程序正常退出,当最后一个非守护线程退出或调用 exit(等效于 System.exit)方法时,或

  • 虚拟机响应用户中断(例如键入 ^C)或系统范围的事件(例如用户注销或系统关闭)而终止。

您的代码无限期运行,因此永远不会调用关闭挂钩。

[修改后]

你用哪个kill

kill -9 是不可捕获的

kill -2 可用于模拟 ctrl-c (SIGINT)

于 2012-10-31T13:21:23.603 回答