具有多个线程的java关闭钩子

具有多个线程的java关闭钩子,java,multithreading,shutdown-hook,Java,Multithreading,Shutdown Hook,我正试图在我的ubuntu服务器上使用一个关机钩子,但是我似乎有一个以上的线程问题。使用基本的ShutdownHook,当我使用kill终止进程时,以下代码位确实起作用,这意味着关闭行为被激活 public static void main(String[] args) { ShutdownHook shutDown = new ShutdownHook(); shutDown.attachShutDownHook(); while(true){} } 但是,这段代码

我正试图在我的ubuntu服务器上使用一个关机钩子,但是我似乎有一个以上的线程问题。使用基本的ShutdownHook,当我使用
kill
终止进程时,以下代码位确实起作用,这意味着关闭行为被激活

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.");

    }
}
注册新的虚拟机关闭挂钩:

Java虚拟机会关闭,以响应两种 活动:

  • 当最后一个非守护进程线程退出或 调用exit(相当于System.exit)方法,或者

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

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

[编辑后]

您使用哪种
kill

kill-9是不可捕获的


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

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

以我自己的项目为例

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

在我的核心班上

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+C
SIGINT
正常关机?

第二个线程的行为是什么?应用程序是否在不调用关闭行为的情况下停止?你也会说“终止进程”。你这是什么意思?如何终止它?第二个线程只是活动线程的一个示例。在我的实际示例中,它正在侦听端口上的连接,并在程序的整个生命周期中保持活动状态。我用
kill
终止进程。上面的第二个程序不能正常工作,因此我缺少关于多个线程的一些信息。请在调用
kill
后尝试运行
jstack
以查看哪些线程仍在运行。一旦我终止了进程,我就无法运行jstack,它只是说,没有这样的过程,你必须有一些其他的,不包括在这里。我刚刚尝试了您的示例(使用额外的线程),所有这些都按照预期工作:`$JavaShutdownHook ShutdownHook Attached。关闭钩子激活$JavaShutdownhook&[1]4879$ShutdownHook已连接。$kill 4879关闭钩子激活$`我正在使用
kill
,没有额外的参数。它应该是可捕获的,事实上在单线程场景中也能工作是的,我尝试过在没有参数的情况下使用
kill
CTRL+C
。在第一个单线程示例中,这两种方法都可以使用,而且只要我有多个线程,这两种方法都不能使用。也许我在设置线程时遗漏了什么?您是否尝试过使用上面的
Runtime
方法?我不知道这会有什么不同,但也许你是在一个线程上附加一个钩子,而不是JVM…如果可能的话。我使用的是运行时。我更新了我原来的问题,以显示关机本身,然后我真的不知道。我的工作示例似乎与你的相同。我有16个工作线程在运行,它们
实现Runnable
而不是
扩展线程
,但这应该没有什么区别。在shutdown hook中的
run()
方法的第一行是否有
System.out.println
或类似内容?它一定在跑!