Why does Java scheduleWithFixedDelay work with Runnable, but not with FutureTask <?> Quits?

Why does Java scheduleWithFixedDelay work with Runnable but not FutureTask, which wraps runnable?

This can be easily shown using 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); 

gives:

Sound signal

But the application does not exit, it just seems to be waiting.

but

 ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); executorService.scheduleWithFixedDelay(new Runnable() { @Override public void run() { System.out.println("beep "); } }, 1, 5, TimeUnit.SECONDS); 

gives:

beep beep beep beep beep beep

with an interval of 5 seconds.

It seems that some kind of castle is taking place here, which I cannot determine.

+6
java concurrency scheduled-tasks
source share
2 answers

Because you are kind of abusing FutureTask .

A FutureTask is a “nullable asynchronous computation” according to Javadocs, but more colloquially it wraps around a particular Runnable / Callable execution to provide asynchrony. I really did not understand that he implemented Runnable until I checked just now - the run() implementation "sets this Future as the result of its calculation".

So what happens in the first example is that you are planning a future task, its start method is called after 1 second, and therefore it calculates the result of the calculation (i.e., it starts the built-in Runnable ). When this method completes, FutureTask now starts and has a concrete result - so future calls to run () are not op operations.

I think the root problem here is that there seems to be no reason to plan FutureTask directly, at least not like you are here. If you want some code to run every five seconds, you should definitely take the second approach. FutureTask embodies (single!) Calculation; there is no reason why you want it to be called multiple times, and in fact it specifically caches the result to prevent this.

+13
source share

You do not have to pass FutureTask objects to the ScheduledExecutorService , you have to go to Runnable or Callable , which then returns you FutureTask . The fact that FutureTask implements the Runnable interface seems to be an unfortunate design flaw, allowing you to pass the output back as input.

As for why you get this behavior, there may be some kind of weird interaction between components and maybe undefined.

+3
source share

All Articles