3

我目前正在评估各种并发解决方案来解决业务问题。该用例类似于“令人尴尬的并行”算法。

基本上对于单个用户请求,我们需要在计算响应之前从多个不同的数据源中检索数据。目前所有 3 个 DAO 调用都是串行进行的,但没有相互依赖关系,因此可以并行进行。

目前实施的解决方案:

  • java.util.concurrent.ExecutorService 使用 Callables 和 Futures
  • org.springframework.scheduling.annotation.Async 启用 spring 管理线程池,但仍然允许我进行异步调用
  • Akka(被认为是矫枉过正)用于我们相对简单的用例

我想评估的最后一个框架是 Java ForkJoin 框架,我可以看到多个使用 RecursiveTasks 的示例,但我的用例本质上不是递归的,因此不适合模型:如果任务足够小,则拆分它并递归调用相同的方法(即分而治之)

我的用例是将任务拆分为 3 个任务。分叉所有 3 并再次加入。这甚至是 ForkJoin 实现的有效用例吗?或者我应该坚持使用通用的 ExecutorService 实现。

4

4 回答 4

0

正如您已经提到的,您的用例中不涉及任何递归。如果您只需要并行运行 3 个任务并等待它们完成,ExecutorService.invokeAll这似乎是最简单的解决方案。

于 2012-07-04T09:54:16.087 回答
0

对于只有 3 个并行任务,最简单的方法是运行 3 个线程,并使用 thread.join() 等待它们完成。

于 2012-07-04T10:03:13.970 回答
0

ExecutorService 的优点是它可以保留线程池。因此,在您的情况下,对于多个连续调用,线程将被重用,这为操作系统节省了一些周期来停止和创建新线程。

ForkJoinPool 的另一个优点是它可以“窃取”工作。AFAIK,这意味着它允许一个已完成任务的线程立即执行另一项任务,其开销比 ExecutorService 少得多。

在您的情况下, ForkJoinPool 的优势似乎很小。

于 2012-07-04T10:22:11.933 回答
0

绝对不是 ForkJoinPool。

在 javadoc 中声明,您必须避免推送任何可能导致任何 IO 的任务,除非在某些情况下输出到异步流。

任务也不应该执行阻塞 IO……100 到 10000 个基本计算步骤。

因此,最好将容器并发管理或 ExecutorServices 与 Futures 一起使用。

于 2012-07-05T18:40:49.390 回答