调用 Timer.cancel() 时,由 java.util.Timer 启动的运行线程的行为是什么?

发布于 2024-12-25 12:59:55 字数 398 浏览 1 评论 0原文

http://docs.oracle.com/javase /1.5.0/docs/api/java/util/Timer.html

这个问题的原因是我有一个以一分钟间隔运行的计时器,它发出的网络请求有时需要长达 5 秒的时间才能完成解析,然后写入文件 磁盘。

当应用程序终止时,我需要清理文件处理程序,但如果计时器启动的线程当前在网络调用上被阻止,并且可能稍后尝试写入已关闭的文件处理程序,我不想这样做。

很难确定性地测试在任意时间点调用 Timer.stop() 时会发生什么,因此我希望使用 Java 或已经解决了类似问题的人能够来帮忙。

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html

The reason for this question is that I have a timer running at one-minute intervals which makes a network request that sometimes takes up to 5 seconds to resolve, and then writes to a file on disk.

When the application is terminated, I need to clean up the file handlers, but I don't want to do that if the timer-initiated thread is in currently blocked on a network call, and may attempt to write to a closed file handler later.

It's hard to test deterministically what happens when Timer.stop() is called at an arbitrary point in time, so I'm hoping that someone who either works on Java or has solved a similar problem might be able to help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

っ〆星空下的拥抱 2025-01-01 12:59:55

从您的更新来看,您的意思似乎是 Timer.cancel ,它解释了它的作用。

/**
 * Terminates this timer, discarding any currently scheduled tasks.
 * Does not interfere with a currently executing task (if it exists).
 * Once a timer has been terminated, its execution thread terminates
 * gracefully, and no more tasks may be scheduled on it.
 *
 * <p>Note that calling this method from within the run method of a
 * timer task that was invoked by this timer absolutely guarantees that
 * the ongoing task execution is the last task execution that will ever
 * be performed by this timer.
 *
 * <p>This method may be called repeatedly; the second and subsequent
 * calls have no effect.
 */
public void cancel() {
    synchronized(queue) {
        thread.newTasksMayBeScheduled = false;
        queue.clear();
        queue.notify();  // In case queue was already empty.
    }
}

我假设您的意思是 javax.swing.Timer 因为 java.util.Timer 没有 stop() 方法,并且 javax.management.timer.Timersun.misc.Timer (有 stop() 方法,但相当晦涩)

AFAIK,使用此计时器进行 IO 是一个非常糟糕的主意,因为它使用 GUI 线程,可能会导致它会锁定一段时间 时间。

查看代码,

/**
 * Stops the <code>Timer</code>,
 * causing it to stop sending action events
 * to its listeners.
 *
 * @see #start
 */
public void stop() {
    getLock().lock();
    try {
        cancelEvent();
        timerQueue().removeTimer(this);
    } finally {
        getLock().unlock();
    }
}

您可以看到它停止发送新任务,但会中断或 stop() 正在运行的任务。

From your update, it appears you mean Timer.cancel which explains what it does.

/**
 * Terminates this timer, discarding any currently scheduled tasks.
 * Does not interfere with a currently executing task (if it exists).
 * Once a timer has been terminated, its execution thread terminates
 * gracefully, and no more tasks may be scheduled on it.
 *
 * <p>Note that calling this method from within the run method of a
 * timer task that was invoked by this timer absolutely guarantees that
 * the ongoing task execution is the last task execution that will ever
 * be performed by this timer.
 *
 * <p>This method may be called repeatedly; the second and subsequent
 * calls have no effect.
 */
public void cancel() {
    synchronized(queue) {
        thread.newTasksMayBeScheduled = false;
        queue.clear();
        queue.notify();  // In case queue was already empty.
    }
}

I assume you mean javax.swing.Timer as java.util.Timer doesn't have a stop() method, and javax.management.timer.Timer and sun.misc.Timer (have stop() methods but are rather obscure)

AFAIK, Its a very bad idea to use this timer for IO as it uses the GUI thread and can cause it to lock up for periods of time.

Looking at the code

/**
 * Stops the <code>Timer</code>,
 * causing it to stop sending action events
 * to its listeners.
 *
 * @see #start
 */
public void stop() {
    getLock().lock();
    try {
        cancelEvent();
        timerQueue().removeTimer(this);
    } finally {
        getLock().unlock();
    }
}

You can see it stop sending new tasks, but does interrupt or stop() running ones.

诗化ㄋ丶相逢 2025-01-01 12:59:55

您是否在守护进程模式下使用计时器?请参阅此文档,其中说明了什么是守护线程。

/**
 * Creates a new timer whose associated thread may be specified to
 * {@linkplain Thread#setDaemon run as a daemon}.
 * A daemon thread is called for if the timer will be used to
 * schedule repeating "maintenance activities", which must be
 * performed as long as the application is running, but should not
 * prolong the lifetime of the application.
 *
 * @param isDaemon true if the associated thread should run as a daemon.
 */
public Timer(boolean isDaemon) {
    this("Timer-" + serialNumber(), isDaemon);
}

如果您使用守护程序线程,应用程序将不会等待该线程完成,因此不能保证该线程中的任何挂起操作完成。但是,如果它不是守护线程,则应用程序只有在该线程完成其最后一个操作后才会关闭。

谈到关闭文件句柄,为什么不在计时器线程本身中执行此操作呢?如果无法做到这一点,关闭挂钩是在应用程序关闭时执行某些操作的理想方法。

因此,您可以拥有一个公共锁,计时器可以在每次任务执行时获取该锁,并且关闭任务可以获取相同的锁来关闭打开的文件句柄。

我希望这能让事情变得清楚。

Are you using the Timer in daemon mode? Please see this documentation which says what's a daemon thread.

/**
 * Creates a new timer whose associated thread may be specified to
 * {@linkplain Thread#setDaemon run as a daemon}.
 * A daemon thread is called for if the timer will be used to
 * schedule repeating "maintenance activities", which must be
 * performed as long as the application is running, but should not
 * prolong the lifetime of the application.
 *
 * @param isDaemon true if the associated thread should run as a daemon.
 */
public Timer(boolean isDaemon) {
    this("Timer-" + serialNumber(), isDaemon);
}

If you are using a daemon thread, application will not wait for this thread to finish so any pending operation in this thread is not guaranteed to finish. However, if it's not a daemon thread, the application will shutdown only after this thread finishes its last operation.

Coming to the closing of file handles, why don't you do that in the timer thread itself? If that cannot be done, Shudown hooks are the ideal way to do something at the application shutting down time.

So, you can have a common lock, which can be acquired by the timer for every task execution and the same lock can be acquired by the shutdown task to close the open file handles.

I hope that makes things clear.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文