Java计时器

dgsult0t  于 2023-01-07  发布在  Java
关注(0)|答案(4)|浏览(201)

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

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

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

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)
cngwdvgl

cngwdvgl1#

您不能像现在这样重用TimerTask。
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();
    }
}

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

ctzwtxfj

ctzwtxfj2#

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

bsxbgnwa

bsxbgnwa3#

在本例中,“已执行......”将在延迟4秒后打印。之后,将每3秒连续打印一次:

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.....
        */
    }
}
dphi5xsq

dphi5xsq4#

您可以使用ScheduledExecutorService,它允许您在不使用scheduleAtFixedRate的情况下多次调度同一个任务。

ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
Runnable timerTask = new Runnable() {
    @Override
    public void run() {
        // Do something
        System.out.println("Task run!");
        // Schedule again
        executorService.schedule(this, 15, TimeUnit.SECONDS);
    }
};
// Schedule
executorService.schedule(timerTask, 15, TimeUnit.SECONDS);

相关问题