我遇到了以下问题:为了执行性能原因,我需要跨多个线程分割工作,但我不知道采取什么方法.
首先,我将提供的任务应该返回一个值并获取一个参数.另外,主要方法(做主工作,而不是静态main())已经在单独的线程上运行,并且被定期调用.此外,该方法必须在某个时间点等待所有线程完成,然后继续.
一种方法(对我来说最明显的)是在单独的线程上安排每个作业,并将结果存储在类vars中:
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方法中访问,除非它们是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 }
解决方法
您使用ExecutorService的方法几乎是最现代和最安全的方法.只需提取您的Callable来分离课程:
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); } }
这将使您的代码更清洁:
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();
几个注释:
> 16个线程太多了,如果你只想同时处理两个任务 – 或者你想从多个客户端线程重用该池?
记得关闭游泳池
>使用轻量级ExecutorCompletionService
等待完成的第一个任务,不一定是提交的第一个任务.
如果您需要完全不同的设计思想,请查看akka及其基于actor的并发模型).