英文:
How do I create a daemon which executes TimerTasks?
问题
我需要在Java中创建一个守护进程,定期通过HTTP检索数据并将其存储在数据库中。
当主线程启动时,它从配置文件中读取数据源和轮询间隔,并为每个数据源创建一个具有适当间隔的TimerTask
。此外,它调用Runtime.getRuntime().addShutdownHook()
来添加一个在关闭之前执行任何所需清理的关闭钩子。在此之后,主线程没有其他事情要做。
该守护进程旨在在经典的Unix环境中使用,即通过启动/停止脚本进行控制,尽管它应该可以在其他操作系统中移植(比如,使用SrvAny的Windows)。
我应该如何处理这个问题?如果我只允许主线程退出,TimerTask
实例会保持VM运行直到所有这些实例都被取消吗?如果不能,我应该如何实现这一点?
英文:
I need to create a daemon in Java which periodically retrieves data via HTTP and stores that in a database.
When the main thread starts up, it reads the data sources and poll intervals from a configuration file and creates a TimerTask
with the appropriate interval for each data source. In addition, it calls Runtime.getRuntime().addShutdownHook()
to add a shutdown hook which performs any cleanup needed before shutdown. After that, the main thread has nothing else to do.
The daemon is intended for use in a classic Unix environment, i.e. controlled with a start/stop script, though it should be portable to other OSes (say, Windows with SrvAny).
How would I go about this? If I just let the main thread exit, will the TimerTask
instances keep the VM running until all of them have been cancelled? If not, how would I accomplish this?
答案1
得分: 1
依赖于安排了 TimerTask
的 Timer
:如果该 Timer
被创建为非守护进程运行其任务,即使主线程完成工作后,挂起的 TimerTask
也将保持虚拟机的活动状态。对于所有不带有 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 来实现。SIGHUP
和 SIGTERM
作用相同。
SIGCONT
没有影响;SIGUSR1
导致强制退出(可能与 SIGKILL
相同),即在不执行关闭钩子的情况下退出。
英文:
It depends on the Timer
on which the TimerTask
was scheduled: if that Timer
was created not to run its tasks as daemons, a pending TimerTask
will keep the VM alive even after the main thread has finished its work. This is the case for all Timer
constructors which do not take a boolean
argument, or where the boolean
argument is false
.
The following seems to work as intended:
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…");
}
}
}
It prints Still running…
every 2 seconds. When the JVM receives a SIGTERM
, the program prints Received shutdown request!
and exits. This can also be accomplished by sending Ctrl+C from the console. SIGHUP
does the same as SIGTERM
.
SIGCONT
has no effect; SIGUSR1
results in a hard exit (presumably the same as SIGKILL
), i.e. without executing the shutdown hook.
答案2
得分: 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)
英文:
Threads in Java have a flag to indicate if they should keep the jvm alive or not. This flag is called "daemon": the jvm will exit when only daemon threads are running.
The thread started by Timer is not a daemon thread by default, so it will keep the jvm alive, which is what you want. If you wanted the jvm to exit, you could create the timer with new Timer(true)
- this would set the daemon flag. https://docs.oracle.com/javase/10/docs/api/java/util/Timer.html#%3Cinit%3E(boolean)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论