Java定时器

新手上路,请多包涵

我正在尝试使用计时器来安排应用程序中的重复事件。但是,我希望能够实时调整事件触发的时间(根据用户输入)。

例如:

 public class HelperTimer extends TimerTask
{
    private Timer timer;
    //Default of 15 second between updates
    private int secondsToDelay = 15;

    public void setPeriod(int seconds)
    {
        this.secondsToDelay = seconds;
        long delay = 1000; // 1 second
        long period = 1000*secondsToDelay; // seconds
        if (timer != null)
        {
            timer.cancel();
        }
        System.out.println(timer);
        timer = new Timer();
        System.out.println(timer);
        timer.schedule(this, delay, period);
    }
    public int getPeriod()
    {
        return this.secondsToDelay;
    }
}

然后我启动这个类的一个新实例并调用它的 set period 函数。但是,当我这样做时,我得到一个非法状态异常。你可以看到 System.out.println(timer);在那里,因为我正在检查,是的,确实,它们是两个不同的计时器……那么为什么当我尝试在全新的 Timer 实例上运行计划调用时我会收到 IllegalStateException !?!?!?!

 java.util.Timer@c55e36
java.util.Timer@9664a1
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Task already scheduled or cancelled
    at java.util.Timer.sched(Unknown Source)
    at java.util.Timer.schedule(Unknown Source)
    at HelperTimer.setPeriod(HelperTimer.java:38)

原文由 Zak 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 499
2 个回答

您不能像在此处那样重复使用 TimerTask。

定时器 的相关部分:

 private void sched(TimerTask task, long time, long period) {
    if (time < 0)
        throw new IllegalArgumentException("Illegal execution time.");

    synchronized(queue) {
        if (!thread.newTasksMayBeScheduled)
            throw new IllegalStateException("Timer already cancelled.");

        synchronized(task.lock) {
            //Right here's your problem.
            //  state is package-private, declared in TimerTask
            if (task.state != TimerTask.VIRGIN)
                throw new IllegalStateException(
                    "Task already scheduled or cancelled");
            task.nextExecutionTime = time;
            task.period = period;
            task.state = TimerTask.SCHEDULED;
        }

        queue.add(task);
        if (queue.getMin() == task)
            queue.notify();
    }
}

您需要重构您的代码,以便创建一个新的 TimerTask,而不是重复使用一个。

原文由 Kevin Montrose 发布,翻译遵循 CC BY-SA 2.5 许可协议

有一个 TimerTask 里面有自己的 Timer 对我来说似乎很奇怪。糟糕的设计。我会将两者完全分开,并将 TimerTask 实现移交给 Timer,并将所有关于摆弄时间段的逻辑放在另一个类中,该类提供了这样做的接口。让那个类实例化 Timer 和 TimerTask 并让它们去做它们的工作。

原文由 duffymo 发布,翻译遵循 CC BY-SA 2.5 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题