有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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函数。然而,当我这样做时,我会得到一个非法的状态异常。你可以看到这个系统。出来println(定时器);在那里,因为我正在检查,是的,他们是两个不同的计时器。。。那么,当我尝试在一个全新的计时器实例上运行计划调用时,为什么会出现非法状态异常

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)

共 (3) 个答案

  1. # 1 楼答案

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

  2. # 2 楼答案

    你不能像现在这样重复使用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,而不是重复使用

  3. # 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.....
        }
        }