ThreadPool不按顺序运行任务

发布于 2024-10-07 23:25:01 字数 357 浏览 8 评论 0原文

我正在使用 Executor 框架,特别是 Executors.newCachedThreadPool();
我有一个 Runnable 列表,例如 100 个。
前 50 个,每个创建一个值(存储在列表中)供后 50 个使用。
我认为,如果我按照列表中的顺序传递 executor.execute() 中的 Runnable,它们将是 也以相同的顺序执行。
但这并没有发生。
这些任务似乎是按随机顺序执行的,并且它们是交错执行的,而不是按顺序执行的。
这是它应该如何工作的吗?有办法解决这个问题吗?

谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

花开半夏魅人心 2024-10-14 23:25:01

您需要分两批提交作业,或者以其他方式创建显式的“发生之前”关系。建议构建两批作业并使用 invokeAll(batch1); invokeAll(batch2); invokeAll() 方法将执行所有任务并阻塞,直到它们完成。您可能需要将 Runnable 包装为 Callable,可以使用 Executors.callable(Runnable r) 来实现。 (@Cameron Skinner 让我获得了一些代码示例,请参阅该答案以获取更多信息...)

执行器的全部要点是抽象出执行的细节,因此除非明确说明,否则不能保证顺序。如果您想要严格顺序执行,请在您正在运行的线程中执行(最简单),在单线程执行器中执行,ala Executors.newSingleThreadExecutor(),或显式同步任务。如果您想执行后者,您可以使用屏障或锁存器,并将相关任务块放在屏障/锁存器上。您还可以让第一个任务块实现 Callable,返回 Future,并让依赖任务调用 myFuture.get(),这会导致他们阻塞直到结果返回。

如果您详细说明您的具体应用,我们也许能够提供更具体的帮助。

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.

水水月牙 2024-10-14 23:25:01

这是正确的行为。您无法保证 Runnable 的执行顺序。

执行器以并行方式运行,而您似乎希望任务以串行方式运行。您可以提交前 50 个作业,等待它们完成,然后提交后 50 个作业,或者(如果执行顺序很重要)仅在单个线程中运行它们。

例如,

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

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);
与风相奔跑 2024-10-14 23:25:01

也许您可以执行前 50 个、shutdownawaitTermination,然后才执行其他 50 个?有关一些示例代码,请参阅此答案

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文