以最小的开销并行执行同一类中的方法

时间:2015-03-25 09:43:36

标签: java parallel-processing

我有一个类算法,它有2个复杂,耗时的方法,比如method1和method2。我必须创建这个类的多个实例,并查询resp。方法1和方法2并行地用于这些实例中的每一个。以下代码几乎实现了这一点:

private final List<Algorithm> algorithms;

private final ExecutorService executor;
private final List<Future<Void>> futures;

public AlgorithmManager(List<Algorithm> algorithms){
    this.algorithms=algorithms;

    //Define workers
    executor = Executors.newFixedThreadPool(Constants.MAXTHREADS); //Creates a threat pool consisting of MAXTHREADS threats
    futures=new ArrayList<Future<Void>>(algorithms.size());
}

/**
 * Procedure to solve method1 for each algorithm in parallel
 */
public double[] solveMethod1(){
    double[] results=new double[algorithms.size()];
    List<FutureTask<Double>> taskList=new ArrayList<FutureTask<Double>>();

    //submit all the relevant tasks to solve method1
    for(Algorithm pp : algorithms){
        FutureTask<Double> futureTask = new FutureTask<Double>(new Callable<Double>() {
            @Override
            public Double call() {
                return pp.solveMethod1();  //SolveMethod1
            }
        });

        taskList.add(futureTask);
        executor.submit(futureTask);
    }

    //Query the results of each task one by one
    for(int i=0; i<algorithms.size(); i++){
        results[i]=taskList.get(i).get();
    }

    return results;
}

/**
 * Procedure to solve method2 for each algorithm in parallel
 */
public int[] solveMethod2(){
    int[] results=new double[algorithms.size()];
    List<FutureTask<Integer>> taskList=new ArrayList<FutureTask<Integer>>();

    //submit all the relevant tasks to solve method1
    for(Algorithm pp : algorithms){
        FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {
            @Override
            public Integer call() {
                return pp.solveMethod2();  //SolveMethod2
            }
        });

        taskList.add(futureTask);
        executor.submit(futureTask);
    }

    //Query the results of each task one by one
    for(int i=0; i<algorithms.size(); i++){
        results[i]=taskList.get(i).get();
    }

    return results;
}

困扰我的是每次创建的FutureTask对象引起的开销,每次调用solveMethod1或solveMethod2时(这种情况经常发生!)。问题是,根据JavaDoc,你不能重用FutureTask对象,即我不能多次执行相同的FutureTask,所以每次我想要执行任何方法时,我都必须创建一个新的对象实例。 我已经考虑过使类算法可调,从而添加一个方法:

@Override
public Double call() throws Exception {
    return this.method1();
}

这样我就可以简单地将Algorithm实例提交给执行者,但我只能为1个方法执行此操作? 有关如何以干净有效的方式改进此实施的任何建议?不幸的是,将method1和method2放入2个不同的类中是不可取的,因为它们高度依赖于彼此的数据结构。

顺便说一句,这是一个简化的代码片段。在我的实际代码中,method1和method2也可以抛出异常。

1 个答案:

答案 0 :(得分:1)

开销可能很小,但使用FutureTasks会使代码不必要地复杂化。所以我建议你使用Callables&amp; amp;来简化和清理你的代码。而是期货。简而言之,您可以使用以下方法并将它们插入代码中相关的位置。

Callable<Double> c = new Callable<Double> () { ... };
Future<Double> f = executor.submit(c);
Double result = f.get();