Java定时器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1041675/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:36:26  来源:igfitidea点击:

Java Timer

javatimer

提问by Zak

I'm trying to use a timer to schedule a recurring event in an application. However, I want to be able to adjust the period at which the event fires in real time (according to the users input).

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

For example:

例如:

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;
    }
}

I then start a new instance of this class and call its set period function. However, when I do that, I get an Illegal state exception. You can see the System.out.println(timer); in there because I'm checking, and yep sure enough, they are two different timers... so why am I getting an IllegalStateException when I try to run a schedule call on a brand new Timer instance!?!?!?!

然后我启动这个类的一个新实例并调用它的 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)

采纳答案by Kevin Montrose

You can't reuse a TimerTask as you're doing here.

您不能像在这里那样重用 TimerTask。

Relevant porition of Timer:

Timer的相关部分:

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();
    }
}

You'll need to refactor your code so that you create a new TimerTask, rather than re-using one.

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

回答by duffymo

It seems odd to me to have a TimerTask with its own Timer inside it. Bad design. I'd totally separate the two and have the TimerTask implementation be handed off to a Timer, and put all that logic about fiddling with the period inside another class that provides an interface for doing so. Let that class instantiate the Timer and TimerTask and send them off to do their work.

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

回答by deeban

    import java.util.*;
    class TimeSetting 
    {
    public static void main(String[] args)
    {
    Timer t = new Timer();
    TimerTask time = new TimerTask()
    { 
    public void run()
    {
    System.out.println("Executed......");
    }
    };
    t.scheduleAtFixedRate(time, 4000, 3000); 
    // The task will be started after 4 secs and 
    // for every 3 seconds the task will be continuously executed.....
    }
    }