ExecutorService Future ::变得非常慢

时间:2017-01-16 20:25:23

标签: java multithreading performance future executorservice

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

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

这是为什么?如何处理它运行得更快?在多线程中有没有办法直接在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<MolecularFormula> formulas_for_exact_method = multimap.get(sortedHeuScores[i]);
        for (final MolecularFormula formula : formulas_for_exact_method){
            Future<Double> exactScore = service.submit(new Callable<Double>() {
                @Override
                public Double call() throws Exception {
                    return getScore(computeTreeExactly(computeGraph(formula)));
                }
            });
            presortedExScores[index] = exactScore.get();
        }

    }

1 个答案:

答案 0 :(得分:2)

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

来自get()的javadoc:

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

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

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

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

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

foreach X
  create future X.i
  wait/get future X.i
你可以做点什么

foreach X
  create future X.i

foreach X
  wait/get for future X.i

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

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

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

另一个非常重要的外卖:不要盲目地使用一些“发生”工作的代码。编程的一个要素是理解源代码中使用的每个和任何概念。您应该非常清楚代码在之前运行它并查找“哦,get()使事情变得缓慢”。

相关问题