我有一个由多个线程访问的类,每个线程请求此类的一个方法。每种方法依次执行多个Callables。此类使用ExecutorService中的threadPool通过invokeAll((Collection>)executableTasks)方法执行这些Callables。 设置如下:
public MyClass {
private final ExecutorService threadPool = Runtime.getRuntime().availableProcessors();
public void method1() {
List<SomeObject> results = new ArrayList<>();
List<Callable<Void>> tasks = new ArrayList<Callable<Void>>();
tasks.add(new Callable<Void>(){ ... results.add(someObject);} );
threadPool.invokeAll(tasks);
}
public void method2() {
List<SomeObject> results = new ArrayList<>();
List<Callable<Void>> tasks = new ArrayList<Callable<Void>>();
tasks.add(new Callable<Void>(){ ... results.add(someObject);} );
threadPool.invokeAll(tasks);
}
}
如果这将同时在类中执行任务或者invokeAll()将阻止执行直到一个方法中的任务完成(意味着执行将在方法内同时发生而不是在类级别),我感到困惑?或者我应该使用CompletionService来找出相应的任务结果吗?
答案 0 :(得分:2)
ExecutorService#invokeAll同时执行所有任务,但调用本身会阻塞,直到所有任务完成。
例如,假设您有三个任务需要6秒,2秒和10秒才能完成。如果要同步执行这些操作,则至少需要6 + 2 + 10 = 18秒。但是,使用invokeAll(在足够大的线程池上),这可能只需要最长的时间,或10秒。
这意味着由于method1()
的使用,方法method2()
和invokeAll()
都是阻止方法。当您调用method1()
时,它将阻塞,直到添加到可调用项列表中的所有请求都完成为止。同样适用于method2()
。如果从不同的线程调用这些方法,则两个方法中的任务将同时执行。
如果希望方法是异步的,则需要为方法内的每个任务单独调用threadPool.submit(callable),并在列表中收集返回的future。你可以返回一个List或使用CompletionService来帮助解决这个问题,是的。
PS - 示例中的这一行不起作用:
ExecutorService threadPool = Runtime.getRuntime().availableProcessors();
我想你想要这个:
ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
希望这有帮助。
答案 1 :(得分:0)
对我来说,这将同时在类中执行任务。 invokeAll()
等待所有任务完成但是当前线程正在等待,而此线程正在等待,其他线程可以同时执行其任务
答案 2 :(得分:-1)
根据Java规范invokeAll
同时独立地执行所有任务。并且对invokeAll
的重复调用也会这样做,也就是说,对invokeAll
的调用不会阻止执行任务。
访问:http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/AbstractExecutorService.html