java ThreadPool 不按顺序运行任务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4470492/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ThreadPool does not run tasks in sequence
提问by Cratylus
I am using the Executor
framework specifically Executors.newCachedThreadPool();
I have a list of Runnable
s 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 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?
我正在使用该Executor
框架,Executors.newCachedThreadPool();
我有一个Runnable
s列表,例如 100。
前 50 个,每个创建一个值(存储在列表中)供最后 50 个使用。
我想,如果我按顺序传递Runnable
sexecutor.execute()
它们在列表中,它们也会以相同的顺序执行。
但这并没有发生。
这些任务似乎是按随机顺序执行的,它们是交错的,而不是按顺序执行的。
这是它应该如何工作?有什么办法可以解决这个问题?
Thanks
谢谢
回答by andersoj
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 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...)
您需要分两批提交作业,或者以其他方式创建明确的“先发生”关系。建议建设的工作两批,并使用invokeAll(batch1); invokeAll(batch2);
该invokeAll()
方法,直到他们完成将执行所有任务和块。您可能需要将Runnable
s包装为Callable
s,您可以使用Executors.callable(Runnable r)
. (@Cameron Skinner 击败我获得了一些代码示例,请参阅该答案以了解更多信息...)
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.
执行器的全部意义在于抽象出执行的细节,因此除非明确说明,否则无法保证排序。如果您想要严格顺序执行,请在您正在运行的线程中执行(最简单),在单线程执行程序中执行,alaExecutors.newSingleThreadExecutor()
或显式同步任务。如果你想做后者,你可以使用屏障或闩锁,并在屏障/闩锁上放置相关任务块。您还可以让第一个任务块实现Callable
、返回Future
并调用依赖任务myFuture.get()
,这会导致它们阻塞直到返回结果。
If you say more about your specific application, we might be able to help more specifically.
如果您详细说明您的具体应用,我们或许可以提供更具体的帮助。
回答by Cameron Skinner
That is the correct behaviour. You have no guarantees about which order the Runnables are executed.
这是正确的行为。您无法保证 Runnable 的执行顺序。
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.
执行程序并行运行,而您似乎希望任务串行运行。您可以提交前 50 个作业,等待它们完成,然后提交后 50 个作业,或者(如果执行顺序很重要)只在单个线程中运行它们。
For example,
例如,
for (Future<Whatever> f: service.invokeAll(first50tasks)) {
addResultToList(f.get());
}
Future<Whatever> output = service.invokeAll(second50tasks);
回答by Fabian Steeg
Perhaps you could execute
the first 50, shutdown
and awaitTermination
, and only then execute
the other 50? See this answerfor some sample code.
也许你可以execute
第50,shutdown
和awaitTermination
,然后才是execute
其他50?有关一些示例代码,请参阅此答案。