First of all, I must say that I am quite new to the API java.util.concurrent, so maybe what I am doing is completely wrong.
What do I want to do?
I have a Java application that basically runs 2 separate processing (called myFirstProcess, mySecondProcess), but these processing must be run at the same time.
So, I tried to do that:
public void startMyApplication() { ExecutorService executor = Executors.newFixedThreadPool(2); FutureTask<Object> futureOne = new FutureTask<Object>(myFirstProcess); FutureTask<Object> futureTwo = new FutureTask<Object>(mySecondProcess); executor.execute(futureOne); executor.execute(futureTwo); while (!(futureOne.isDone() && futureTwo.isDone())) { try { // I wait until both processes are finished. Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } logger.info("Processing finished"); executor.shutdown(); // Do some processing on results ... }
myFirstProcess and mySecondProcess are classes that implements Callable<Object>
, and where all their processing is made in the call() method.
It is working quite well but I am not sure that it is the correct way to do that. Is a good way to do what I want? If not, can you give me some hints to enhance my code (and still keep it as simple as possible).
A FutureTask can be used to wrap a Callable or Runnable object. Because FutureTask implements Runnable , a FutureTask can be submitted to an Executor for execution. In addition to serving as a standalone class, this class provides protected functionality that may be useful when creating customized task classes.
Future is a base interface and defines the abstraction of an object which promises results to be available in the future while FutureTask is an implementation of the Future interface.
util. concurrent package. This package has a set of classes and interfaces that helps in developing concurrent applications (multithreading) in java. Before this package, one needs to make the utility classes of their need on their own.
util. concurrent. Future , represents the result of an asynchronous computation. When the asynchronous task is created, a Java Future object is returned. This Future object functions as a handle to the result of the asynchronous task.
You'd be better off using the get()
method.
futureOne.get(); futureTwo.get();
Both of which wait for notification from the thread that it finished processing, this saves you the busy-wait-with-timer you are now using which is not efficient nor elegant.
As a bonus, you have the API get(long timeout, TimeUnit unit)
which allows you to define a maximum time for the thread to sleep and wait for a response, and otherwise continues running.
See the Java API for more info.
The uses of FutureTask
above are tolerable, but definitely not idiomatic. You're actually wrapping an extra FutureTask
around the one you submitted to the ExecutorService
. Your FutureTask
is treated as a Runnable
by the ExecutorService
. Internally, it wraps your FutureTask
-as-Runnable
in a new FutureTask
and returns it to you as a Future<?>
.
Instead, you should submit your Callable<Object>
instances to a CompletionService
. You drop two Callable
s in via submit(Callable<V>)
, then turn around and call CompletionService#take()
twice (once for each submitted Callable
). Those calls will block until one and then the other submitted tasks are complete.
Given that you already have an Executor
in hand, construct a new ExecutorCompletionService
around it and drop your tasks in there. Don't spin and sleep waiting; CompletionService#take()
will block until either one of your tasks are complete (either finished running or canceled) or the thread waiting on take()
is interrupted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With