У меня есть алгоритм класса, который имеет 2 сложных, трудоемких метода, например method1 и method2. Я должен создать несколько экземпляров этого класса, и запрос соответственно. метод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 каждый раз при вызове методаMethod1 или solveMethod2 (это происходит очень часто!). Проблема в том, что, согласно JavaDoc, вы не можете повторно использовать объект FutureTask, т.е. Я не могу выполнить один и тот же FutureTask несколько раз, поэтому мне нужно создать новый экземпляр объекта каждый раз, когда я хочу выполнить любой из этих методов. Я подумал о том, чтобы сделать класс Алгоритм вызываемым, тем самым добавив метод:
@Override
public Double call() throws Exception {
return this.method1();
}
Таким образом, я могу просто представить экземпляры Algorithm для исполнителя, но я могу сделать это только для одного метода? Любые предложения о том, как улучшить эту реализацию, чистым и эффективным образом? К сожалению, нежелательно ставить method1 и method2 на 2 разных класса, поскольку они сильно зависят от структур данных друг от друга.
Btw, это упрощенный фрагмент кода. В моем реальном коде методы method1 и method2 также могут генерировать исключения.
Накладные расходы, вероятно, минимальны, но ваш код излишне усложняется с помощью FutureTasks. Поэтому я предлагаю вам упростить и очистить свой код, используя вместо этого Callables & Futures. Короче говоря, вы можете использовать следующие методы и вставлять их, если это необходимо в вашем коде.
Callable<Double> c = new Callable<Double> () { ... };
Future<Double> f = executor.submit(c);
Double result = f.get();