【问题标题】:Java ExecutorService - sometimes slower than sequential processing?Java ExecutorService - 有时比顺序处理慢?
【发布时间】:2013-09-24 23:40:31
【问题描述】:

我正在编写一个简单的实用程序,它接受一组可调用任务,并并行运行它们。希望总时间比最长任务所花费的时间少。该实用程序还添加了一些错误处理逻辑 - 如果任何任务失败,并且失败可以被视为“可重试”(例如超时或用户指定的异常),那么我们直接运行任务。

我已经围绕 ExecutorService 实现了这个实用程序。分为两部分:

  1. submit() 所有 Callable 任务到 ExecutorService,存储 Future 对象。
  2. 在 for 循环中,get() 每个 Future 的结果。如果出现异常,请执行“可重试”逻辑。

我编写了一些单元测试以确保使用此实用程序比按顺序运行任务更快。对于每个测试,我会生成一定数量的 Callable,每个基本上都会在一定范围内随机执行 Thread.sleep()。我尝试了不同的超时、不同数量的任务等,该实用程序似乎优于顺序执行。

但是当我将它添加到需要这种实用程序的实际系统中时,我看到的结果非常多变 - 有时并行执行更快,有时更慢,有时更快,但仍然需要很多时间比最长的单项任务更多的时间。

我只是做错了吗?我知道 ExecutorService 有 invokeAll() 但这会吞噬底层异常。我还尝试使用 CompletionService 按完成顺序获取任务结果,但它表现出或多或少相同的行为。我现在正在阅读有关闩锁和障碍的内容 - 这是解决此问题的正确方向吗?

【问题讨论】:

  • 你可以考虑使用 Akka (akka.io) 来解决这个问题
  • 如果有帮助,提醒您接受答案。

标签: java multithreading performance executorservice


【解决方案1】:

我编写了一些单元测试以确保使用此实用程序比按顺序运行任务更快。对于每个测试,我会生成一定数量的 Callable,每个基本上都会在一定范围内随机执行 Thread.sleep()

是的,这当然不是一个公平的测试,因为它既不使用 CPU 也不使用 IO。我当然希望并行睡眠比串行睡眠运行得更快。 :-)

但是当我将它添加到需要这种实用程序的实际系统中时,我看到的结果非常多变

没错。线程应用程序是否比串行应用程序运行得更快在很大程度上取决于许多因素。特别是,IO 绑定应用程序不会提高性能,因为它们受 IO 通道约束,因此实际上无法进行并发操作。应用程序需要的处理越多,将其转换为多线程的胜利就越大。

我做错了吗?

没有更多细节很难知道。您可能会考虑使用并发运行的线程数。如果您有大量工作要处理,您不应该使用Executos.newCachedThreadPool(),而应该根据您的架构拥有的 CPU 数量优化newFixedSizeThreadPool(...)

您可能还想看看是否可以将 IO 操作隔离在几个线程中并将处理隔离到其他线程。就像一个从文件读取的输入线程和一个输出线程(或一对)写入数据库之类的东西。因此,对于不同类型的任务,多个大小的池可能比使用单个线程池更好。

尝试使用 CompletionService 按完成顺序获取任务结果

如果您要重试操作,则使用 CompletionService 是正确的方法。当作业完成并抛出异常(或返回失败)时,它们可以重新启动并立即放回线程池中。我看不出您的性能问题会因此而产生的任何原因。

【讨论】:

  • 嗨,格雷,感谢您的详细回复。确实,我的实际任务是执行 I/O 操作——在 Lucene 索引中搜索。我想我必须深入研究文档,看看是否有一种有效的方法来并行搜索。我的线程池是一个固定的线程池,可容纳 32 个线程。
  • @RuslanD 可能获得的最大胜利是将该框切换为使用 SSD。改进 IO 链可能是提高其速度的最佳方法,而不是花时间在线程上。在某个时候,随着 IO 链不再成为瓶颈,线程是否是必要的。
  • 我希望我能在我的组织中做出这样的硬件决策 :) 现实情况是系统在一堆主机上运行,​​而它们没有/不会有 SSD。所以我需要想办法获得更好的性能,而不是简单地按顺序运行 I/O 任务。
  • 是的,明白了。内存文件系统也会给你同样的性能提升@RuslanD。
【解决方案2】:

多线程编程不是免费的。它有一个开销。开销很容易超过和性能增益,通常会使您的代码更加复杂。

额外的线程可以访问更多的 cpu 功率(假设您有备用 cpu),但通常它们不会让您的 HDD 旋转得更快,给您更多的网络带宽或加速不受 cpu 限制的东西。

多线程可以帮助您获得更大的外部资源份额。

【讨论】:

    猜你喜欢
    • 2021-02-22
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多