(similar to "Resettable Java Timer" but there are some subtleties I need to explore)
I need a resettable timeout feature, so that if my class does not perform a particular action within an interval of time T0 (where T0 is in the neighborhood of 50-1000msec), then a method gets called:
class MyClass {
static final private timeoutTime = 50;
final private SomeTimer timer = new SomeTimer(timeoutTime,
new Runnable () { public void run() {
onTimeout();
}});
private void onTimeout() { /* do something on timeout */ }
public void criticalMethod() { this.timer.reset(); }
}
What can I use to implement this? I'm familiar with ScheduledExecutorService, and the idea of calling ScheduledFuture.cancel() and then rescheduling the task seems like it should work, but then there's a potential hazard if cancel() fails and the scheduled task executes when it shouldn't. I feel like I'm missing a subtlety here.
Also (perhaps more importantly), is there a way to test my implementation / prove that it works properly?
edit: I am particularly concerned about the case where criticalMethod()
gets called often (perhaps several times per millisecond)... if I use ScheduledExecutorService, it just seems like a potential resource problem to keep creating new scheduled tasks + canceling old ones, rather than having a direct way to reschedule a task.
ok, here's an attempt at using ScheduledExecutorService. I'm impressed by the performance; I ran the test program with arguments 50 1 10 (50msec timeout; every 1msec the ResettableTimer is reset 10 times) and it uses virtually none of my CPU.
The cancelled attribute is attached to the task object. So, either the task hasn't started when you call
cancel
, and it won't get run; or the task has already started when you callcancel
, and it gets interrupted.How to handle interruption is up to you. You should regularly poll
Thread.interrupted()
(which, by the way, resets the interrupted flag, so beware) if you aren't calling any interruptible function (ones that declareInterruptedException
in theirthrows
clause).Of course, if you are calling such functions, you should handle
InterruptedException
sensibly (which includes reasserting the interrupted flag (Thread.currentThread().interrupt()
) before your task returns). :-)To answer your edit, object creation is cheap, as long as your object doesn't have a lot of state. I personally wouldn't worry about it too much unless profiling shows it to be a bottleneck.