gpt4 book ai didi

Java 并发迭代 : Divide and Conquer vs Runnable for each item

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:03:52 27 4
gpt4 key购买 nike

当我有数百个项目要迭代时,我必须对每个项目执行计算量大的操作,我会采用“分而治之”的方法。本质上,我会将处理器计数 + 1,并将这些项目分成相同数量的批处理。然后我将在缓存线程池中的可运行对象上执行每个批处理。它似乎运作良好。我的 GUI 任务从 20 秒减少到 2 秒,这对用户来说是一个更好的体验。

但是,我在阅读 Brian Goetz 关于并发性的好书时注意到,为了遍历项目列表,他会采用完全不同的方法。他会为每个项目启动一个 Runnable!以前,我一直推测这会很糟糕,尤其是在可以创建大量线程的缓存线程池上。然而,每个可运行的可能会在更大的范围内很快完成,而且我知道缓存的线程池对于短任务来说是非常理想的。

那么迭代计算量大的项目时,哪种范式更容易被接受?分成固定数量的batch,给每batch一个runnable?还是在其自己的可运行程序中启动每个项目?如果后一种方法是最优的,那么使用缓存线程池好还是使用有界线程池更好?

最佳答案

对于批处理,您将始终需要等待运行时间最长的批处理(您与最慢的批处理一样快)。 “分而治之”意味着管理开销:为划分进行管理,为征服进行监控。

为每个项目创建一个任务相对简单(无需管理),但你是对的,它可能会启动数百个线程(不太可能,但它可能会发生),这只会减慢速度(上下文切换)如果任务不执行/执行很少的 I/O,主要是 CPU 密集型。

如果缓存线程池没有启动数百个线程(参见 getLargestPoolSize ),那么一定要使用缓存线程池。如果启动了太多线程,那么一种替代方法是使用有界线程池。但是有界线程池需要一些调整/决定:您使用无界任务队列还是带CallerRunsPolicy的有界任务队列?例如?

附带说明:还有 ForkJoinPool适用于启动子任务的任务。

关于Java 并发迭代 : Divide and Conquer vs Runnable for each item,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24714997/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com