我有以下代码:
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会话。
您是否有任何关于等待登录终止的背景的建议?
答案 0 :(得分:2)
ShutdownHook是一个在JVM退出时执行的线程,并且在执行“sendMessage”后程序没有执行任何操作:
sendMessage(event, getCurrentLogin());
您应该等待信号退出,例如控制台上的Ctrl + C. 只需等待锁定或信号量以避免程序完成,并且当您需要完成锁定时应该释放该锁定。
答案 1 :(得分:1)
我在您的示例中添加了一个锁存器,以尝试使示例正常工作。遗憾的是,我没有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";
}
}
答案 2 :(得分:0)
如果我理解正确,你想无限期等待,直到操作系统停止你的程序,是吗?如果是这样,您需要至少运行一个守护程序线程:
public static void main(String[] args) throws InterruptedException {
//...
final Object o = new Object();
synchronized(o) {
while(true) {
o.wait();
}
}
}
我不确定操作系统是否会轻轻地杀死JVM,并且关闭钩子会执行。测试一下。
答案 3 :(得分:0)
应用程序完成时会调用shutdown hook。因此,如果您想让应用程序永远运行,您需要实现以下内容:
while (true) {
//Your logic here
}
如果你想编写一个守护进程或调度程序,你可能需要使用一些框架作为Quartz http://quartz-scheduler.org
如果要实现守护程序,可以使用服务包装程序,如http://yajsw.sourceforge.net或http://wrapper.tanukisoftware.com/
答案 4 :(得分:0)
这里有一些很好的答案,但我仍然看到一些缺失的信息。
您的代码在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();
}
}
}
您希望在注册关闭挂钩后开始等待,以便执行您的shudown代码。
答案 5 :(得分:-1)
这是一种使用CountDownLatch
来保持主线程等待的方法:
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();
}