2011-07-28 77 views
3

所以我有这段Java代码,我需要在一堆项目上做一些工作。我决定将其并行化以获得一些额外的提升,但我仍然使用ThreadPoolExecutor。问题是,我需要做的工作可以抛出异常...在ThreadPool中报告异常并关闭

现在我想关闭整个工作,一遇到错误就停下来,并报告回来,以便我可以处理它。在网上查看时,我发现通过ExecutorCompletionService和分析未来结果的正常方式。但是,当第一个错误出现时,这不会让我关闭所有的东西,因为没有办法根据哪个任务先完成循环...

所以我做了一些我认为是相当黑客和我很好奇,如果有更好的方法来处理这个问题。我所做的是:

1)让每个我将执行的Runnable都有一个可执行Throwable的字段。 2)覆盖TPE的“afterExecute”方法,并检查是否有任何检查的异常被抛出(记录在Runnable中)或任何未被检查的异常被抛出(应该在此方法的第二个参数中报告)。如果有的话,我在TPE上发出shutdownNow()。

同样,这似乎有点hacky,我想知道是否有什么我失踪。提前致谢!

+0

是否需要停止其他任务执行刚性测试,在第一次失败后甚至执行单个测试是灾难性的?或者它是一个“有益”的要求,因为如果其他任务保持运行一段时间就可以了,但是越快它们停下来越好?我问,因为即使说“第一次失败来临”在并行执行环境中也不清楚,因为没有仔细的同步,你不知道在不同线程上执行任务的顺序。 –

+0

你明白了“很高兴”的要求,因为我只想通知所有并行任务,当他们中的一个遇到错误时应立即停止。当然,由于线程在池中运行的方式,这可能并不意味着“尽快”,但这是一个原则性的事情。 实际上,您可以将其视为具有启动我的ThreadPool的阻止调用,并且我希望这可以报告结果,如果一切正常,或尽快解除阻止以最大限度地提高可用性。 –

回答

2

ExecutorService.invokeAny

执行给定的任务,返回一个已成功完成(即未抛出异常)的结果,如果任何事情。在正常或异常返回时,尚未完成的任务将被取消。如果在进行此操作时修改了给定集合,则此方法的结果未定义。

它看起来确实和你想要做的事情完全相同......如果我正确理解你的问题。

但是,要取消任何操作,您必须让您的Callable任务中断。但是,无论您如何取消任务,这都适用。

编辑
这不是你所需要的;我误解了javadoc。以下是另一种解决方案:您可以将所有Future列入清单,然后有一个半忙的while循环,您可以定期检查每个futureList.get(i).get(100, TimeUnits.MILLISECONDS),您可以捕获异常并采取相应的行动。然而,这不比你的解决方案更“优雅”。看起来afterExecute是为了做你想做的。

+1

如果我的帖子误解了,我表示歉意,但如果没有遇到任何错误,我需要完成所有并行任务 - 这就是为什么我说我只是在线程之间分割工作。 invokeAny方法似乎在任何一个任务完成后立即返回,这符合“并行最佳结果计算”风格,而不是工作负载splittin ... –

+0

我误解了javadoc。还有'invokeAll',但它似乎没有以任何方式处理任务的异常。 – toto2

+0

@Bogdan看到我的编辑。 – toto2