2012-01-17 60 views
1

我有以下代码:设置ShutdownHook和退出应用

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会话。

您是否有任何关于后台等待登录终止的建议?

回答

2

的ShutdownHook是,当JVM在退出,程序是不是做你执行“的sendMessage”后,任何执行一个线程:

sendMessage(event, getCurrentLogin()); 

您应该等待一个信号退出,像在控制台上按Ctrl + C。 只需等待锁定或信号即可避免程序终结,并且在需要完成时应释放该锁定。

0

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

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

我不知道泰德操作系统将取消JVM轻轻足够,并且关闭钩子将执行,但。测试它。

-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(); 
} 
+1

你打我吧:-) – Scorpion 2012-01-17 16:16:13

+0

我没有看到InterruptedException的处理? – Scorpion 2012-01-17 16:50:03

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"; 
     } 
    } 
+0

这不会编译,因为锁定不是最终的。看到我的答案是正确的方式;) – dogbane 2012-01-17 16:22:20

+0

更正了它,并没有给出一个声明,这只是一个想法,而不是一个工作解决方案。 – Scorpion 2012-01-17 16:48:16

0

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

您的代码在main中注册了一个关闭钩子,然后主要到达终点并返回。当最后一个非守护进程线程退出时,关闭钩子被调用。我怀疑main是唯一的非守护线程,所以当main退出钩子时立即被调用。

如果您不想让程序立即退出,那么main将不得不循环并等待某种信号。从你的问题的上下文中,我想它应该倾听来自sendMessage呼叫的某种响应?如果你想等待控制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代码被执行您注册关闭挂钩。