Bob*_*r02 11 java multithreading executorservice
我提出了以下问题:出于性能原因,我需要跨多个线程拆分工作,但我不确定采取什么方法.
首先,我将提供的任务应该返回一个值并获取一个参数.另外,主要方法(做主要工作,而不是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
}
Run Code Online (Sandbox Code Playgroud)
这有点难看并且不太理想,因为正如我所说,mainMethod被多次调用,我不希望在设置结果变量时有任何竞争条件.理想情况下,我想让它们成为局部变量,但我不能在run方法中访问它们,除非它们是final,然后我不能为它们赋值......
另一种方法,我虽然这样做是这样的:
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
}
Run Code Online (Sandbox Code Playgroud)
这会自动从main方法等待这两个计算,并允许我在本地存储结果.你觉得怎么样?还有其他方法吗?
Tom*_*icz 13
您的方法ExecutorService几乎是最现代和最安全的方法.建议将Callables 提取到单独的类:
public class ExpensiveTask implements Callable<String> {
private final String param;
public ExpensiveTask(String param) {
this.param = param;
}
@Override
public String call() throws Exception {
return expensiveMethod(param);
}
}
Run Code Online (Sandbox Code Playgroud)
这将使您的代码更清洁:
final ExecutorService executorService = Executors.newFixedThreadPool(16);
final Future<String> res1 = executorService.submit(new ExpensiveTask("param1"));
final Future<String> res2 = executorService.submit(new ExpensiveTask("param2"));
String obj1 = res1.get();
String obj2 = res2.get();
Run Code Online (Sandbox Code Playgroud)
几点说明:
如果您只想同时处理两个任务,或者您想要从多个客户端线程重用该池,那么16个线程太多了?
记得关闭游泳池
使用轻量级ExecutorCompletionService等待完成的第一个任务,不一定是第一个提交的任务.
如果您需要完全不同的设计理念,请查看akka及其基于actor的并发模型.