设置ShutdownHook并退出应用程序

发布于 2024-12-27 14:55:20 字数 768 浏览 4 评论 0原文

我有以下代码:

public static void main(String[] args) {

    // login event
    String event = "login";
    System.out.printf("Handling event: %s %s\n",event,getCurrentLogin());
    sendMessage(event, getCurrentLogin());

    // logout or shutdown event
    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
        @Override
        public void run() {
                String event = "logout";
                System.out.printf("Handling event: %s %s\n",event,getCurrentLogin());
                sendMessage(event, getCurrentLogin());
        }
    }));
 }

这是一个非常简单的程序,用于记录用户的登录和注销。问题是程序在到达函数 main() 末尾时退出。

我是否正确使用了关闭事件挂钩? 我不想创建一个复杂的 Windows 服务,它必须是一个非常简单的应用程序,因为它将用于远程连接的 Windows 会话。

您对后台等待登录终止有什么建议吗?

I have the following code:

public static void main(String[] args) {

    // login event
    String event = "login";
    System.out.printf("Handling event: %s %s\n",event,getCurrentLogin());
    sendMessage(event, getCurrentLogin());

    // logout or shutdown event
    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
        @Override
        public void run() {
                String event = "logout";
                System.out.printf("Handling event: %s %s\n",event,getCurrentLogin());
                sendMessage(event, getCurrentLogin());
        }
    }));
 }

It's a very simple program for logging user's login and logout. The problem is that the program exits when reaches the end of function main().

Am I using to the shutdown event hook correctly?
I don't want to create a complex windows service, it must be a very simple application cause it will be used for remote connected windows sessions.

Do you have any suggesion for background waiting for the login termination ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

旧伤慢歌 2025-01-03 14:55:20

ShutdownHook 是一个线程,当 JVM 退出并且程序在执行“sendMessage”后没有执行任何操作时执行:

sendMessage(event, getCurrentLogin());

您应该等待退出信号,例如控制台上的 Ctrl+C。
只需等待锁或信号量来避免程序终止,并且当您需要完成它时应该释放该锁。

The ShutdownHook is a thread that is executed when the JVM is exiting and the program is not doing anything after you execute the "sendMessage":

sendMessage(event, getCurrentLogin());

You should wait for a signal to exit, like a Ctrl+C on the console.
Just wait for a lock or Semaphore to avoid the program finalization, and that lock should be released when you need to finish it.

牛↙奶布丁 2025-01-03 14:55:20

我已在您的示例中添加了一个闩锁,以尝试使该示例正常工作。不幸的是,我没有 IDE 来测试,但这应该足以提供一个想法。

编辑:下面的示例将打印登录和注销。

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

    public class Test {
        public static void main(String[] args) throws Exception {

            // login event
            String event = "login";
            System.out.printf("Handling event: %s %s\n", event, getCurrentLogin());
            sendMessage(event, getCurrentLogin());
            final CountDownLatch latch = new CountDownLatch(1);

            // logout or shutdown event
            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
                @Override
                public void run() {
                    String event = "logout";
                    System.out.printf("Handling event: %s %s\n", event, getCurrentLogin());
                    sendMessage(event, getCurrentLogin());
                    latch.countDown();
                }
            }));
            latch.await(2, TimeUnit.SECONDS);
        }

        private static void sendMessage(String event, Object currentLogin) {
        }

        private static Object getCurrentLogin() {
            return "X";
        }
    }

I have added a latch to your example to try to make the example work. I unfortunately do not have an IDE to test, but this should be enough to give an idea.

EDIT : The example below would print both login and logout.

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

    public class Test {
        public static void main(String[] args) throws Exception {

            // login event
            String event = "login";
            System.out.printf("Handling event: %s %s\n", event, getCurrentLogin());
            sendMessage(event, getCurrentLogin());
            final CountDownLatch latch = new CountDownLatch(1);

            // logout or shutdown event
            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
                @Override
                public void run() {
                    String event = "logout";
                    System.out.printf("Handling event: %s %s\n", event, getCurrentLogin());
                    sendMessage(event, getCurrentLogin());
                    latch.countDown();
                }
            }));
            latch.await(2, TimeUnit.SECONDS);
        }

        private static void sendMessage(String event, Object currentLogin) {
        }

        private static Object getCurrentLogin() {
            return "X";
        }
    }
等风也等你 2025-01-03 14:55:20

如果我理解正确的话,您想无限等待直到操作系统停止您的程序,对吗?如果是这样,您需要至少运行一个守护线程:

public static void main(String[] args) throws InterruptedException {
    //...
    final Object o = new Object();
    synchronized(o) {
        while(true) {
            o.wait();
        }
    }
}

我不确定操作系统是否会足够温和地终止 JVM,但关闭挂钩是否会执行。测试一下。

If I understand correctly, you want to wait infinitely until the OS stops your program, is that right? If so, you need to have at least one daemon thread running:

public static void main(String[] args) throws InterruptedException {
    //...
    final Object o = new Object();
    synchronized(o) {
        while(true) {
            o.wait();
        }
    }
}

I'm not sure thet the OS will kill the JVM gently enough, and that the shutdown hook will execute, though. Test it.

人生百味 2025-01-03 14:55:20

当应用程序完成时,关闭钩子被调用。因此,如果你想让你的应用程序永远运行,你需要实现一些东西:

while (true) {
    //Your logic here
}

如果你想编写一个守护进程或调度程序,也许你需要使用一些框架,如 Quartz http://quartz-scheduler.org

如果你想实现一个守护进程,你可以使用像 http://yajsw.sourceforge.nethttp://wrapper.tanukisoftware。 com/

The shutdown hook is called when the application finalize. So if you want to let you application run forever you need to implement something as:

while (true) {
    //Your logic here
}

If you want to write a daemon or scheduler maybe you need to use some framework as Quartz http://quartz-scheduler.org

If you want to implement a daemon you can use a Service Wrapper like http://yajsw.sourceforge.net or http://wrapper.tanukisoftware.com/

小苏打饼 2025-01-03 14:55:20

这里有一些很好的答案,但我仍然看到一些缺失的信息。

您的代码在 main 中注册一个关闭钩子,然后 main 到达末尾并返回。当最后一个非守护线程退出时,关闭钩子被调用。我怀疑 main 是唯一的非守护线程,因此当 main 退出时,会立即调用钩子。

如果您不希望程序立即退出,则 main 将必须循环并等待某种信号。从您问题的上下文来看,我想它应该监听来自 sendMessage 调用的某种响应?如果你想等待 control-c 那么我喜欢 @JB Nizet 的回答:

public static void main(String[] args) throws InterruptedException {
    ...
    Runtime.getRuntime().addShutdownHook(...);
    // wait until control-c is called
    final Object o = new Object();
    synchronized(o) {
        while(true) {
            o.wait();
        }
    }
}

你想在注册关闭钩子之后开始等待,以便执行关闭代码。

There are some good answers here but I still see some missing information.

Your code registers a shutdown hook in main and then main reaches the end and returns. The shutdown hooks are called when the last non-daemon thread exits. I suspect that main is the only non-daemon thread so when main exits the hook is immediately called.

If you don't want your program to exit immediately then main will have to loop and wait for some sort of signal. From the context of your question, I guess it should be listening for some sort of response from sendMessage call? If you want to wait for control-c then I like @JB Nizet's answer for this:

public static void main(String[] args) throws InterruptedException {
    ...
    Runtime.getRuntime().addShutdownHook(...);
    // wait until control-c is called
    final Object o = new Object();
    synchronized(o) {
        while(true) {
            o.wait();
        }
    }
}

You want to start waiting after you register your shutdown hook so your shudown code gets executed.

淡忘如思 2025-01-03 14:55:20

这是一种使用 CountDownLatch< /code>让主线程保持等待:

public static void main(String[] args) {

    // login event
    String event = "login";
    System.out.printf("Handling event: %s %s\n",event,getCurrentLogin());
    sendMessage(event, getCurrentLogin());

    final CountDownLatch latch = new CountDownLatch(1);

    // logout or shutdown event
    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
        @Override
        public void run() {
                String event = "logout";
                System.out.printf("Handling event: %s %s\n",event,getCurrentLogin());
                sendMessage(event, getCurrentLogin());
                latch.countDown();
        }
    }));

    latch.await();
 }

Here is one approach using a CountDownLatch to keep the main-thread waiting:

public static void main(String[] args) {

    // login event
    String event = "login";
    System.out.printf("Handling event: %s %s\n",event,getCurrentLogin());
    sendMessage(event, getCurrentLogin());

    final CountDownLatch latch = new CountDownLatch(1);

    // logout or shutdown event
    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
        @Override
        public void run() {
                String event = "logout";
                System.out.printf("Handling event: %s %s\n",event,getCurrentLogin());
                sendMessage(event, getCurrentLogin());
                latch.countDown();
        }
    }));

    latch.await();
 }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文