Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java's FutureTask composability

I try to work with Java's FutureTask, Future, Runnable, Callable and ExecutorService types.

What is the best practice to compose those building blocks?

Given that I have multiple FutureTasks and and I want to execute them in sequence.

Ofcourse I could make another FutureTask which is submitting / waiting for result for each subtask in sequence, but I want to avoid blocking calls.

Another option would be to let those subtasks invoke a callback when they complete, and schedule the next task in the callback. But going that route, how to I create a proper outer FutureTask object which also handles exceptions in the subtask without producing that much of a boilerplate?

Do I miss something here?

like image 523
Nappy Avatar asked Feb 05 '13 10:02

Nappy


1 Answers

Very important thing, though usually not described in tutorials:

Runnables to be executed on an ExecutorService should not block. This is because each blocking switches off a working thread, and if ExecutorService has limited number of working threads, there is a risk to fall into deadlock (thread starvation), and if ExecutorService has unlimited number of working threads, then there is a risk to run out of memory. Blocking operations in the tasks simply destroy all advantages of ExecutorService, so use blocking operations on usual threads only.

FutureTask.get() is blocking operation, so can be used on ordinary threads and not from an ExecutorService task. That is, it cannot serve as a building block, but only to deliver result of execution to the master thread.

Right approach to build execution from tasks is to start next task when all input data for the next task is ready, so that the task do not have to block waiting for input data. So you need a kind of a gate which stores intermediate results and starts new task when all arguments have arrived. Thus tasks do not bother explicitly to start other tasks. So a gate, which consists of input sockets for arguments and a Runnable to compute them, can be considered as a right building block for computations on ExcutorServices.

This approach is called dataflow or workflow (if gates cannot be created dynamically).

Actor frameworks like Akka use this approach but are limited in the fact that an actor is a gate with single input socket.

I have written a true dataflow library published at https://github.com/rfqu/df4j.

like image 55
Alexei Kaigorodov Avatar answered Oct 13 '22 10:10

Alexei Kaigorodov