Reputation: 4073
I am trying to build more or less a watchdog class. If a value hasn't changed for a certain time, the class should do something. Therefore I want to utilize a standard timer, the idea is to set a timer, and reset it as soon as the watched value changes.
public class Watchdog {
public final Timer TIMER = new Timer(true);
public final long DELAY;
public Watchdog(long delay){
DELAY=delay;
valueChanged();
}
public void valueChanged(){
TIMER.cancel();
TIMER.purge();
TIMER.schedule(new TimerTask() {
@Override
public void run() {
Watchdog.this.alarm();
}
}, DELAY);
}
public void alarm(){
System.out.println("Watchdog barked");
}
}
Unfortunately I get an IllegalStateException every time I call TIMER.cancel()
, as there is no timer set at the first call. What am I doing wrong? How to reset the timer, even if there is no timer set?
EDIT Stacktrace
Exception in thread "main" java.lang.IllegalStateException: Timer already cancelled.
at java.util.Timer.sched(Timer.java:397)
at java.util.Timer.schedule(Timer.java:193)
at deleteme.Watchdog.valueChanged(Watchdog.java:28)
at deleteme.Watchdog.<init>(Watchdog.java:22)
at deleteme.Deleteme.main(Deleteme.java:19)
Java Result: 1
Upvotes: 0
Views: 3845
Reputation: 2125
According to the Timer source code, the cancel method changes the value of an internal flag called newTasksMayBeScheduled to false.
public void cancel() {
synchronized(queue) {
thread.newTasksMayBeScheduled = false;
queue.clear();
queue.notify(); // In case queue was already empty.
}
}
The value of this flag is checked prior to scheduling a new task and it fires the exception you get as it is false.
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
I think that you should use the cancel method of the TimerTask instead of Timer. For the sake of completeness of the answer, note that an alternative would be to use ScheduledThreadPoolExecutor.
Upvotes: 1