可复位的 Java 计时器

2022-09-01 03:05:30

我想有一个java.utils.Timer,在java中具有可重置的时间。我需要设置一个 once off 事件,在 X 秒内发生。如果在创建计时器的时间和 X 秒之间没有任何反应,则该事件将照常发生。

但是,如果在 X 秒过去之前,我决定该事件应该在 Y 秒之后发生,那么我希望能够告诉计时器重置其时间,以便事件在 Y 秒内发生。例如,计时器应该能够执行如下操作:

Timer timer = new Timer();  
timer.schedule(timerTask, 5000); //Timer starts in 5000 ms (X)

//At some point between 0 and 5000 ms...  
setNewTime(timer, 8000);  //timerTask will fire in 8000ms from NOW (Y).

我没有看到使用utils计时器执行此操作的方法,就像您调用unde cancel()一样,您无法再次安排它。

我接近复制此行为的唯一方法是使用javax.swing.Timer,并涉及停止原始计时器,并创建一个新的计时器。即:

timer.stop();
timer = new Timer(8000, ActionListener);
timer.start();

有没有更简单的方法??


答案 1

根据 Timer 文档,在 Java 1.5 及更高版本中,您应该更喜欢 ScheduledThreadPoolExecutor。(为了便于使用,您可能希望使用 Executors 创建此执行程序;它创建的东西很像 .).newSingleThreadScheduledExecutor()Timer

很酷的事情是,当你计划一个任务(通过调用)时,它会返回一个SchventEdFuture对象。您可以使用它来取消计划任务。然后,您可以自由提交具有不同触发时间的新任务。schedule()

ETA:链接到的文档没有说明,但是OpenJDK版本是这样说的:TimerScheduledThreadPoolExecutor

Java 5.0引入了该软件包,其中的并发实用程序之一是线程池,用于以给定的速率或延迟重复执行任务。它实际上是/ 组合的更通用的替代品,因为它允许多个服务线程,接受各种时间单位,并且不需要子类化(只需实现)。使用一个线程进行配置使其等效于 。java.util.concurrentScheduledThreadPoolExecutorTimerTimerTaskTimerTaskRunnableScheduledThreadPoolExecutorTimer


答案 2

如果你只有一个任务要执行,那么我建议它进行子类化:Timer

import java.util.Timer;
import java.util.TimerTask;

public class ReschedulableTimer extends Timer
{
    private Runnable  task;
    private TimerTask timerTask;

    public void schedule(Runnable runnable, long delay)
    {
        task = runnable;
        timerTask = new TimerTask()
        {
            @Override
            public void run()
            {
                task.run();
            }
        };
        this.schedule(timerTask, delay);
    }

    public void reschedule(long delay)
    {
        timerTask.cancel();
        timerTask = new TimerTask()
        {
            @Override
            public void run()
            {
                task.run();
            }
        };
        this.schedule(timerTask, delay);
    }
}

您需要处理代码以添加对误用的检查,但它应该实现您想要的。似乎也没有内置对重新安排现有任务的支持,但类似的方法也应该在那里工作。ScheduledThreadPoolExecutor