У меня возникла следующая проблема: мне нужно разделить работу на несколько потоков по причинам производительности, но я не уверен, какой подход выбрать.
Во-первых, задача, которую я бы поставил, должна возвращать значение и принимать параметр. Кроме того, основной метод (выполняющий основную часть работы, а не static main()
) уже выполняется в отдельном потоке и периодически вызывается. Кроме того, этот метод должен в какой-то момент дождаться завершения всех потоков, а затем продолжить работу.
Один из подходов (наиболее очевидный для меня) состоит в том, чтобы запланировать каждое задание в отдельном потоке и сохранить результаты в переменных класса:
public Object result1, result2;
public void mainMethod() throws InterruptedException {
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
result1 = expensiveMethod("param1");
}
});
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
result2 = expensiveMethod("param2");
}
});
thread1.join();
thread.join();
//Do rest of work
}
private Object expensiveMethod(Object param){
// Do work and return result
}
Это немного некрасиво и не идеально, так как, как я уже сказал, mainMethod вызывается много раз, и я не хочу никаких условий гонки при установке переменных результата. В идеале я хотел бы сделать их локальными переменными, но я не могу сделать их доступными из метода запуска, если только они не являются окончательными, и тогда я не могу присвоить им значения...
Другой подход, о котором я думал, заключался в следующем:
public void mainMethod() throws InterruptedException, ExecutionException {
String obj1, obj2;
final ExecutorService executorService = Executors.newFixedThreadPool(16);
final Future<String> res1 = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return expensiveMethod("param1");
}
});
final Future<String> res2 = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return expensiveMethod("param2");
}
});
obj1 = res1.get();
obj2 = res2.get();
}
private String expensiveMethod(String param) {
// Do work and return result
}
Это автоматически ожидает этих двух вычислений из основного метода и позволяет мне сохранять результаты локально. Что вы думаете, ребята? Любые другие подходы?
Future
— разумная идея. - person Kalpak Gadre   schedule 11.10.2012