如何创建一个执行 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 来完成。 SIGHUP
与 SIGTERM
相同。
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)
我需要在 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 来完成。 SIGHUP
与 SIGTERM
相同。
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)