java - invokeAll 与 CompletionService

标签 java concurrency

我有一个由多个线程访问的类,每个线程请求该类的一个方法。每个方法依次执行多个 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来找出任务对应的结果吗?

最佳答案

ExecutorService#invokeAll同时执行所有任务,但调用本身会阻塞,直到所有任务完成。

例如,假设您有三项任务需要 6 秒、2 秒和 10 秒才能完成。如果要同步执行这些,则至少需要 6 + 2 + 10 = 18 秒。但是,使用 invokeAll(在足够大的线程池上),这可能需要最短的时间,即 10 秒。

这意味着方法 method1()method2() 都是阻塞方法,因为使用了 invokeAll()。当您调用 method1() 时,它将阻塞,直到添加到可调用列表中的所有请求都完成为止。 method2() 也是如此。如果从不同的线程调用这些方法,则两个方法中的任务将同时执行。

如果您希望方法是异步的,您需要为方法内的每个任务单独调用 threadPool.submit(callable) 并将返回的 future 收集在列表中。您可以返回一个列表或使用 CompletionService 来帮助实现此目的,是的。

PS - 您的示例中的这一行不起作用:

ExecutorService threadPool = Runtime.getRuntime().availableProcessors();

我认为你想要这个:

ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

希望这有帮助。

关于java - invokeAll 与 CompletionService,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16601038/

相关文章:

java - 需要一个解决方案来设计自动化系统

concurrency - mysqldump并发

java - 使用 java.util.concurrent.Executor 阻止 tomcat 停止

java - 多个线程共享/访问相同数据的问题

java - Android 此功能需要 ASM7

java - 检修台模型 Swing

java - 使用 RestEasy 客户端代理时如何指定 Web 代理?

testing - 运行在 Selenium IDE 中开发的多个测试

python - 在 Web 应用程序中使用 Postgres : "transaction aborted" errors

java - 确定单词是否在文件的单词列表中