ExecutorService Future ::变得非常慢

我正在并行化一个非常复杂的程序来加快速度。 为此,我大部分时间都使用ExecutorService 。 到目前为止它工作得很好,但后来我注意到只有一行代码使我的程序运行速度尽可能快一半。 这是exactScore.get()的行。

我不知道为什么,但它有时需要更多的0.1秒来获得Future Object的double值。

为什么是这样? 如何处理它运行得更快? 在multithreading中有没有办法直接在Double[]编写? 谢谢

 int processors = Runtime.getRuntime().availableProcessors(); ExecutorService service = Executors.newFixedThreadPool(processors); // initialize output Double[] presortedExScores = new Double[sortedHeuScores.length]; for(int i =0; i < sortedHeuScores.length; i++ ){ final int index = i; final Collection formulas_for_exact_method = multimap.get(sortedHeuScores[i]); for (final MolecularFormula formula : formulas_for_exact_method){ Future exactScore = service.submit(new Callable() { @Override public Double call() throws Exception { return getScore(computeTreeExactly(computeGraph(formula))); } }); presortedExScores[index] = exactScore.get(); } } 

这是可以预料的。 那不是“慢”; 它只是在做它的工作。

从javadoc for get() :

如果需要等待计算完成,然后检索其结果。

长话短说:您似乎不理解您在代码中使用的概念。 未来的想法是它在未来的某个时刻做事。

通过调用get()你表达:我不介意等待,直到计算结果“落后”Future变得可用。

因此:你必须退后一步,再次查看你的代码; 了解你的不同“活动线索”是如何运作的; 以及他们如何/何时回到一起。

想到一个想法:现在,您在循环中创建Future对象; 并在创建Future之后直接调用get() 。 这与创建多个期货的想法完全矛盾。 换句话说:而不是去:

 foreach X create future Xi wait/get future Xi 

你可以做点什么

 foreach X create future Xi foreach X wait/get for future Xi 

换句话说:让你的未来真正并行做事; 而不是强制执行顺序处理。

如果这对“足够”没有帮助,那就说:你必须看看你的整体设计,并确定是否有办法进一步“拉开”事物。 现在所有的活动都“密切”在一起; 并且惊讶:当你同时做大量的工作时,这需要时间。 但正如你可能猜到的那样:这样的重新设计可能需要做很多工作; 并且在不了解您的问题/代码库的情况下几乎是不可能的。

更复杂的方法是你编写代码,其中每个Future都有一种表达“我已经完成”的方式 – 那么你将“只”启动所有期货; 并等到最后一个回来。 但正如所说; 我无法在这里为您设计完整的解决方案。

另一个非常重要的外卖:不要盲目地使用一些“发生”的代码。 编程的一个本质是理解源代码中使用的每个概念和任何概念。 运行它之前你应该非常清楚你的代码在做什么,然后找到“哦, get()让事情变得缓慢”。