Why does Java’s scheduleWithFixedDelay work with a Runnable but not a FutureTask wrapping a runnable?
This can be shown pretty easily with two different code samples:
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleWithFixedDelay(new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("beep");
return 1;
}
}), 1, 5, TimeUnit.SECONDS);
produces:
beep
But the application does not exit, it simply appears to wait.
but:
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("beep ");
}
}, 1, 5, TimeUnit.SECONDS);
produces:
beep
beep
beep
beep
beep
at 5 second intervals.
It seems like there is some kind of lock happening here that I cannot determine.
Because you’re kind of abusing
FutureTask.A FutureTask is “a cancellable asynchronous computation” according to the Javadocs, but more colloquially it wraps a particular execution of Runnable/Callable to provide the asynchronicity. I didn’t actually realise that it implemented
Runnableuntil I checked just now – the implementation ofrun()“sets this Future to the result of its computation”.So what’s happening in your first example is that you’re scheduling the future task, its run method gets called after 1 second and so it calculates the result of the computation (i.e. runs the embedded
Runnable). When this method exits, the FutureTask has now run and has its concrete result – so future invocations of run() are no-ops.I think the root problem here is that it doesn’t seem to make sense to schedule a FutureTask directly, at least not in the manner you’re doing here. If you want a bit of code to run every five seconds, then you should definitely take the second approach. The FutureTask embodies a (single!) calculation; there’s no reason why you’d want it to be invoked multiple times and in fact it’s specifically caching the result to prevent this.