У меня возникла следующая проблема: мне нужно разделить работу между несколькими потоками по причинам производительности, но я не уверен, какой подход выбрать.
Во-первых, поставленная мною задача должна вернуть значение и принять параметр. Кроме того, основной метод (выполняющий основную часть работы, а не 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 вызывается много раз, и я не хочу никаких условий гонки при установке переменных результата. В идеале я хотел бы сделать их локальными переменными, но я не могу сделать их доступными из метода run, если они не являются окончательными, и тогда я не могу присвоить им значения...
Еще один подход, о котором я подумал, заключался в следующем:
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
}
Это автоматически ожидает этих двух вычислений из метода main и позволяет мне сохранять результаты локально. Что вы, ребята, думаете? Любые другие подходы?