ThreadPool does not run tasks in sequence

☆樱花仙子☆ 提交于 2019-12-12 11:31:17

问题


I am using the Executor framework specifically Executors.newCachedThreadPool();
I have a list of Runnables e.g. 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 Runnables 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


回答1:


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); The invokeAll() method will execute all of the tasks and block until they complete. You may need to wrap your Runnables as Callables, 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.




回答2:


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);



回答3:


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



来源:https://stackoverflow.com/questions/4470492/threadpool-does-not-run-tasks-in-sequence

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!