简体   繁体   中英

ThreadPool does not run tasks in sequence

I am using the Executor framework specifically Executors.newCachedThreadPool();
I have a list of Runnable s eg 100.
The first 50, each create a value (stored in a list) to be used by the last 50.
I thought that if I pass the Runnable s in the executor.execute() in the order they are in the list, they would be also executed in the same order.
But this is not happening.
The tasks seem to be executed in random order and they are interleaved, not executed in sequence.
Is this how it is suppose to work? Any way to work around this problem?

Thanks

You need to submit the jobs in two batches, or otherwise create an explicit "happens-before" relationship. Suggest building two batches of jobs and using invokeAll(batch1); invokeAll(batch2); invokeAll(batch1); invokeAll(batch2); The invokeAll() method will execute all of the tasks and block until they complete. You may need to wrap your Runnable s as Callable s, which you can do with Executors.callable(Runnable r) . (@Cameron Skinner beat me to getting some code example, see that answer for more...)

The whole point of executors is to abstract away the specifics of execution, so ordering is not guaranteed unless explicitly stated. If you want strictly sequential execution, do it in the thread you're running in (simplest), do it in a single-threaded executor, ala Executors.newSingleThreadExecutor() , or explicitly synchronize the tasks. If you want to do the latter, you could use a barrier or latch and have the dependent tasks block on the barrier/latch. You could also have the first block of tasks implement Callable , return Future , and have the dependent tasks call myFuture.get() which would cause them to block until the results are returned.

If you say more about your specific application, we might be able to help more specifically.

That is the correct behaviour. You have no guarantees about which order the Runnables are executed.

Executors run in parallel , whereas it seems that you want the tasks run in serial . You can either submit the first 50 jobs, wait for them to finish, then submit the second 50 jobs, or (if the order of execution is important) just run them all in a single thread.

For example,

for (Future<Whatever> f: service.invokeAll(first50tasks)) {
    addResultToList(f.get());
}
Future<Whatever> output = service.invokeAll(second50tasks);

Perhaps you could execute the first 50, shutdown and awaitTermination , and only then execute the other 50? See this answer for some sample code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM