Reputation: 33
I have a recursive bulk task that I put into execution in a ForkJoinPool thread pool.
public class SomeTask extends RecursiveAction {
@Override
protected void compute() {
//Some recursive logic...
}
}
public class Main {
public static void main(String[] args) {
startForkJoinPool();
}
private void startForkJoinPool() {
SomeTask someTask = new SomeTask();
ForkJoinPool pool = new ForkJoinPool(4);
pool.invoke(someTask);
pool.shutdown();
}
}
Now I need to execute this logic in two more parallel threads.
I decided to try to use the ExecutorService thread pool, and when I put entities into it for execution, I found out that they are not executed in parallel, but, as it were, one of the threads is parked for the duration of the first one.
public class SomeTask extends RecursiveAction {
@Override
protected void compute() {
//Some recursive logic...
}
}
public class Main {
public static void main(String[] args) {
List<Thread> threadList = new ArrayList<>();
threadList.add(new Thread(() -> startForkJoinPool()));
threadList.add(new Thread(() -> startForkJoinPool()));
ExecutorService executorService = Executors.newFixedThreadPool(2);
threadList.forEach(executorService::execute);
executorService.shutdown();
}
private void startForkJoinPool() {
SomeTask someTask = new SomeTask();
ForkJoinPool pool = new ForkJoinPool(4);
pool.invoke(someTask);
pool.shutdown();
}
}
Tell me, please, what can I do wrong? Many thanks in advance to anyone who can point me in the right direction.
Upvotes: 2
Views: 1177
Reputation: 9384
It is a bit strange that your code example contains ExecutorService.invoke and ExecutorService.execute where you should be calling ExecutorService.submit.
The ExecutorService documentation also contains a usage example. And then there is some nice Java Tutorial on the topic.
Upvotes: 3
Reputation: 338476
execute
to submit
.Executor#execute
is not necessarily asyncYou need to carefully read the documentation. This is a tricky area.
The ExecutorService#execute
method is inherited from the super interface Executor
.
The Javadoc for Executor
says:
However, the
Executor
interface does not strictly require that execution be asynchronous
So any Runnable
you pass to execute
may or may not be run on a background thread.
ExecutorService#submit
is always asyncIf you definitely want your Runnable
to run on a background thread, pass to ExecutorService#submit
.
Change this line:
threadList.forEach(executorService::execute);
… to this:
threadList.forEach(executorService::submit);
Your call to ExecutorService#shutdown
is insufficient. You need to wait for submitted tasks to complete.
See the boilerplate method shutdownAndAwaitTermination
given to you in the Javadoc for ExecutorService
.
Or, in Java 19+, call ExecutorService#close
.
Upvotes: 1
Reputation: 1151
Don't create any threads, that is the job of the ExecutorService.
You don't want to execute
the task, you want to submit
the task. Then you get a Future<T>
returned.
As you already have a collection, consider invokeAll
that returns List<Future<T>>
and saves you iterating through your list.
Upvotes: 2