We have three different multi threading techniques in java - Fork/Join pool, Executor Service & CountDownLatch
Fork/Join pool (http://www.javacodegeeks.com/2011/02/java-forkjoin-parallel-programming.html)
The Fork/Join framework is designed to make divide-and-conquer algorithms easy to parallelize. That type of algorithms is perfect for problems that can be divided into two or more sub-problems of the same type. They use recursion to break down the problem to simple tasks until these become simple enough to be solved directly. The solutions to the sub-problems are then combined to give a solution to the original problem
ExecutorService is an interface that extends Executor class and represents an asynchronous execution. It provides us mechanisms to manage the end and detect progress of the asynchronous tasks.
invokeAll() : Executes the given tasks, returning a list of Futures holding their status and results when all complete. Future.isDone() is true for each element of the returned list.
CountDownLatch:(http://examples.javacodegeeks.com/core-java/util/concurrent/countdownlatch-concurrent/java-util-concurrent-countdownlatch-example/)
CountDownLatch is used in synchronisation to allow one or more threads to wait until a set of operations being performed in other threads completes.
My assumption:
In both these alternatives, final result will be known only after completion of all tasks/threads.
Are these three alternatives complimentary or supplementary to each other?
After research on various multi threading frameworks , I have found answer to question from various oracle documentation pages
It is simple and easy to use with limited control.
I prefer this one when number of Callable/Runnable
tasks are small in number and piling of tasks in unbounded queue does not cause pile-up in memory & degrade the performance of the system.
It hides low level details of ThreadPoolExecutor
. It does not allow playing with other parameters ( Bounded Queue, Rejection Handler
etc. to fine tune the performance) as in ThreadPoolExectuor
.
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler)
It provides more control to you. Apart from setting minimum and maximum threads, you can set queue size and make BlockingQueue
is bounded.
If your application is constrained by number of pending Runnable/Callable tasks, you will use bounded queue by setting the max capacity. Once the queue reaches maximum capacity, you can define RejectionHandler. Java provides four types of Rejection Handler policies.
CountDownLatch
: This framework allows a java thread to wait until other set of threads completes their tasks.
The ForkJoinPool
is similar to the Java ExecutorService but with one difference.
This enables efficient processing when most tasks spawn other subtasks (as do most ForkJoinTasks), as well as when many small tasks are submitted to the pool from external clients
public ForkJoinPool(int parallelism,
ForkJoinPool.ForkJoinWorkerThreadFactory factory,
Thread.UncaughtExceptionHandler handler,
boolean asyncMode)
Regarding main query:
You can use ExecutorService.invokeAll()
or CountDownLatch
framework or ForkJoinPool
. All these frameworks are complimentary to each other varying of granularity to control the execution of tasks from high level to low level.
Have a look at related SE questions: