我正在编写一个简单的实用程序,它接受一组可调用任务,并并行运行它们。希望总时间比最长任务所花费的时间少。该实用程序还添加了一些错误处理逻辑 - 如果任何任务失败,并且失败可以被视为“可重试”(例如超时或用户指定的异常),那么我们直接运行任务。
我已经围绕 ExecutorService 实现了这个实用程序。有两个部分:
- submit() 所有 Callable 任务到 ExecutorService,存储 Future 对象。
- 在 for 循环中,get() 每个 Future 的结果。如果出现异常,请执行“可重试”逻辑。
我编写了一些单元测试以确保使用此实用程序比按顺序运行任务更快。对于每个测试,我会生成一定数量的 Callable,每个基本上都会在一定范围内随机执行 Thread.sleep()。我尝试了不同的超时、不同数量的任务等,并且该实用程序似乎优于顺序执行。
但是当我将它添加到需要这种实用程序的实际系统中时,我看到的结果非常多变——有时并行执行更快,有时更慢,有时更快,但仍然比最长的个人任务。
我只是做错了吗?我知道 ExecutorService 有 invokeAll() 但这会吞噬底层异常。我还尝试使用 CompletionService 按完成顺序获取任务结果,但它表现出或多或少相同的行为。我现在正在阅读有关闩锁和障碍物的内容-这是解决此问题的正确方向吗?