Reputation: 9522
I feel like my java concurrency knowledge is getting rusty, I am trying to figure out why the thread pool doesn't accept more tasks in the following code:
ExecutorService e = Executors.newFixedThreadPool(aNumber);
// Task 1
for (int i=0; i<n; i++)
e.submit(new aRunnable());
while (!e.isTerminated());
System.out.println("Task 1 done");
// Task 2
for (int i=0; i<n; i++)
e.submit(new anotherRunnable());
while (!e.isTerminated());
System.out.println("Task 2 done");
It never gets to start Task 2, the thread "freezes" when the last task from Task 1 one is run like if it was waiting for something else to finish.
What's wrong?
Upvotes: 0
Views: 368
Reputation: 116888
It never gets to start Task 2, the thread "freezes" when the last task from Task 1 one is run like if it was waiting for something else to finish.
It is waiting. ExecutorService.isTerminated()
waits for the thread pool tasks to finish after the pool has been shutdown. Since you've never called e.shutdown();
your loop will spin forever. To quote from the ExecutorService
javadocs:
Returns true if all tasks have completed following shut down. Note that isTerminated is never true unless either shutdown or shutdownNow was called first.
You've not shut the service down so that will never be true. In general, anything that spins in a while
loop like that is an antipattern – at the very least put a Thread.sleep(10);
in the loop. Typically we use e.awaitTermination(...)
but again, that's only after you've called e.shutdown();
. And you don't want to shut the ExecutorService
down because you are going to be submitting more tasks to it.
If you want to wait for all of your tasks to finish then submit more tasks I'd do something like the following and call get()
on the Future
s that are returned from the first batch of submitting tasks. Something like:
List<Future> futures = new ArrayList<Future>();
for (int i = 0; i < n; i++) {
futures.add(e.submit(new aRunnable()));
}
// now go back and wait for all of those tasks to finish
for (Future future : futures) {
future.get();
}
// now you can go forward and submit other tasks to the thread-pool
Upvotes: 5
Reputation: 2122
If you want to know when a specific task finishes, use an ExecutorService, which will return a Future<> (a handle that you can use to get the status of a specific job) -- the executor itself doesn't terminate until you shut it down. Think of an executor like 'batch queue' or a 'coprocessor' waiting around for you to throw some work in the hopper.
Update: Gray answered this much better than I - see his post. -- (how do people type that fast??)
Upvotes: 0