ExecutorService and ForkJoinPool
I have an ExecutorService created as follows -
ExecutorService executorSer = Executors.newFixedThreadPool(SIZE);
I have a list of elements(LIST) and a operation(called A) which i need to apply on every element in this list. The list can contain contain any number of elements between 1 to 1000. The operation is of type Callable. Inside the Operation-A, it makes calls to 2 other services B and C. B and C are also run as async operations and submitted to the same thread pool.
I have created an async task for each to execute this in parallel as follows:
CompletionService<T> completionService = new ExecutorCompletionService<T>(executorSer);
completionService.submit(A) // this returns a Future<T>
Now i have a List of Future which i loop over to get() the result.
If I have a very large thread pool and small number of elements in the LIST, everything works well. However, if the thread pool SIZE is small and LIST size is large, i run into a deadlock. This is because all Operation-A requests are submitted quickly and occupy all the threads in the threadpool. And every Operation-A is blocked on Future.get() of the Operation B and C which it submitted. Operation B and C tasks are just sitting in the queue waiting to get a thread.
SO, to fix this i used ForkJoinPool instead. I simply replaced newFixedThreadPool with ForkJoinPool as follows
ExecutorService executorSer = new ForkJoinPool(SIZE);
and left the rest of the code same.
This solves my problem. There is no deadlock now if the thread pool SIZE is small and LIST size is large. My question is, why? Also, when i print the thread names, i see thread numbers greater than SIZE. Is it just spawning new threads to solve the deadlock?
There is no Executors.ForkJoinPool(SIZE)
method in java.util.concurrent.Executors
class. However, there is Executors.newWorkStealingPool(int parallelism)
method which creates a ForkJoinPool. As the JAVA API is mentioning:
The parallelism level corresponds to the maximum number of threads actively engaged in, or available to engage in, task processing. The actual number of threads may grow and shrink dynamically.
There is your answer. The parameter you provide is not the maximum number of actual threads that will be managed by the executor (like is the case for a FixedThreadPool
executor).