如何创建一个执行 TimerTasks 的守护进程?

How do I create a daemon which executes TimerTasks?

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

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

该守护进程旨在用于经典的 Unix 环境,即由 start/stop 脚本控制,但它应该可以移植到其他操作系统(例如,Windows 和 SrvAny)。

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

这取决于 TimerTask 被安排在哪个 Timer 上:如果 Timer 是创建的 而不是 到 运行 它的任务作为守护进程,挂起的 TimerTask 将使 VM 保持活动状态,即使在主线程完成其工作后也是如此。这是所有 Timer 构造函数的情况,它们不采用 boolean 参数,或者 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 相同),即不执行关闭挂钩。

Java 中的线程有一个标志来指示它们是否应该使 jvm 保持活动状态。此标志称为 "daemon":当只有守护线程 运行.

时,jvm 将退出

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