Java 设置关闭钩子并退出应用程序
我有以下代码:Java 设置关闭钩子并退出应用程序,java,login,event-handling,system-shutdown,shutdown-hook,Java,Login,Event Handling,System Shutdown,Shutdown Hook,我有以下代码: 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
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会话
您是否有任何关于后台等待登录终止的建议?关闭钩子是一个线程,在JVM退出时执行,并且在您执行“sendMessage”后程序不执行任何操作: 您应该等待退出信号,如控制台上的Ctrl+C。
只要等待一个锁或信号量来避免程序终止,当您需要完成它时,应该释放该锁。如果我理解正确,您希望无限期地等待,直到操作系统停止您的程序,对吗?如果是这样,您需要至少运行一个守护进程线程:
public static void main(String[] args) throws InterruptedException {
//...
final Object o = new Object();
synchronized(o) {
while(true) {
o.wait();
}
}
}
不过,我不确定操作系统是否会足够温和地杀死JVM,也不确定关闭挂钩是否会执行。测试它。当应用程序完成时,将调用关闭挂钩。因此,如果您想让应用程序永远运行,您需要实现以下功能:
while (true) {
//Your logic here
}
如果您想编写守护进程或调度程序,可能需要使用一些框架
如果要实现守护程序,可以使用服务包装器,如或,这里有一种方法使用,使主线程保持等待:
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();
}
我在您的示例中添加了一个闩锁,以尝试使示例正常工作。不幸的是,我没有一个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";
}
}
这里有一些很好的答案,但我仍然看到一些缺失的信息 您的代码在
main
中注册一个关机挂钩,然后main到达末尾并返回。当最后一个非守护进程线程退出时,将调用关闭挂钩。我怀疑main是唯一的非守护进程线程,因此当main
退出时,会立即调用钩子
如果不希望程序立即退出,则必须循环并等待某种信号。从你的问题的上下文来看,我想它应该是在听sendMessage
call的某种回应?如果您想等待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();
}
}
}
您希望在注册关闭挂钩后开始等待,以便执行关闭代码。这不会编译,因为锁存不是最终的。请看我的答案,以找到正确的方法;)更正了它,我没有给出一个免责声明,这只是给出一个想法,而不是一个有效的解决方案。我没有看到InterruptedException的处理?
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();
}
}
}