【问题标题】:How do I create a daemon which executes TimerTasks?如何创建一个执行 TimerTasks 的守护进程?
【发布时间】:2020-04-05 16:33:33
【问题描述】:

我需要在 Java 中创建一个守护程序,它定期通过 HTTP 检索数据并将其存储在数据库中。

当主线程启动时,它从配置文件中读取数据源和轮询间隔,并为每个数据源创建一个具有适当间隔的TimerTask。此外,它调用Runtime.getRuntime().addShutdownHook() 添加一个关闭挂钩,该挂钩执行关闭前所需的任何清理。之后,主线程就无事可做。

该守护程序旨在用于经典 Unix 环境,即使用启动/停止脚本进行控制,但它应该可以移植到其他操作系统(例如,带有 SrvAny 的 Windows)。

我该怎么做呢?如果我只是让主线程退出,TimerTask 实例是否会保持 VM 运行,直到它们都被取消?如果没有,我将如何实现?

【问题讨论】:

    标签: java daemon


    【解决方案1】:

    Java 中的线程有一个标志来指示它们是否应该让 jvm 保持活动状态。这个标志被称为“daemon”:当只有守护线程在运行时,jvm 将退出。

    Timer启动的线程默认不是守护线程,所以它会让jvm保持活跃,这正是你想要的。如果您希望 jvm 退出,您可以使用 new Timer(true) 创建计时器 - 这将设置守护程序标志。 https://docs.oracle.com/javase/10/docs/api/java/util/Timer.html#%3Cinit%3E(boolean)

    【讨论】:

      【解决方案2】:

      这取决于计划TimerTaskTimer:如果创建Timer不是将其任务作为守护进程运行,则待处理的TimerTask 将保留VM即使在主线程完成工作后仍然活着。这适用于所有不采用 boolean 参数的 Timer 构造函数,或者 boolean 参数为 false 的情况。

      以下似乎按预期工作:

      package com.example.daemon;
      
      import java.util.Date;
      import java.util.Timer;
      import java.util.TimerTask;
      
      public class SampleDaemon {
          private static Timer testTimer = new Timer(false);
      
          public static void main(String[] args) {
              Runtime.getRuntime().addShutdownHook(new Thread() {
                  @Override
                  public void run() {
                      System.out.println("Received shutdown request!");
                      if (testTimer != null)
                          testTimer.cancel();
                      testTimer = null;
                  }
              });
              testTimer.schedule(new TestTimerTask(), new Date(), 2000);
          }
      
          private static class TestTimerTask extends TimerTask {
              @Override
              public void run() {
                  System.out.println("Still running…");
              }
          }
      }
      

      它每 2 秒打印一次 Still running…。当JVM收到SIGTERM时,程序打印Received shutdown request!并退出。这也可以通过从控制台发送 Ctrl+C 来完成。 SIGHUPSIGTERM 的作用相同。

      SIGCONT 无效; SIGUSR1 导致硬退出(可能与SIGKILL 相同),即不执行关闭挂钩。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-25
        • 2014-04-12
        • 1970-01-01
        • 1970-01-01
        • 2016-03-10
        • 2014-07-03
        • 2011-07-20
        • 1970-01-01
        相关资源
        最近更新 更多