首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否使用invokeAll或submit - java Executor服务

是否使用invokeAll或submit - java Executor服务
EN

Stack Overflow用户
提问于 2015-12-23 17:10:45
回答 3查看 25.8K关注 0票数 26

我有一个场景,在这个场景中,我必须为同一个可调用的线程异步执行5个线程。据我所知,有两种选择:

1)使用submit(可调用)

代码语言:javascript
运行
复制
ExecutorService executorService = Executors.newFixedThreadPool(5);
List<Future<String>> futures = new ArrayList<>();
for(Callable callableItem: myCallableList){
    futures.add(executorService.submit(callableItem));
}

2)使用invokeAll(可调用集合)

代码语言:javascript
运行
复制
ExecutorService executorService = Executors.newFixedThreadPool(5);
List<Future<String>> futures = executorService.invokeAll(myCallableList));
  1. 什么应该是首选的方式?
  2. 与另一种相比,它们中的任何一种是否有任何不利之处或性能影响?
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-01-14 19:57:28

选项1:您将任务提交给ExecutorService,而不是等待已提交给ExecutorService的所有任务的完成

选项2:您正在等待已提交给ExecutorService的所有任务的完成。

什么应该是首选的方式?

根据应用程序的需求,它们中的任何一个都是首选。

  1. 如果您不想在任务提交()到ExecutorService之后等待,请选择Option 1
  2. 如果您需要等待已提交给ExecutorService的所有任务的完成,请选择Option 2

与另一种相比,它们中的任何一种是否有任何不利之处或性能影响?

如果应用程序需要选项2,则必须等待提交给ExecutorService的所有任务完成,这与选项1不同。性能不是比较的标准,因为两者都是为两个不同的目的设计的。

还有一件更重要的事情:无论您喜欢什么选项,FutureTask都会在任务执行期间吞下异常。你一定要小心。看看这个SE问题:处理ThreadPoolExecutor的异常

使用Java 8,您还有一个选项:ExecutorCompletionService

使用提供的执行器执行任务的CompletionService。这个类安排提交的任务在完成后放置在一个队列中,该队列可以使用“取”访问。该类足够轻量级,适合在处理一组任务时使用。

看看相关的SE问题:ExecutorCompletionService?如果我们有invokeAll,为什么需要一个?

票数 28
EN

Stack Overflow用户

发布于 2015-12-23 17:30:09

编辑:

其实他们之间是有区别的。出于某种原因,invokeAll()将为生成的每个future调用get()。因此,它将等待任务完成,这就是它可能抛出InterruptedException (而submit()不抛出任何东西)的原因。

这是invokeAll()方法的Javadoc:

执行给定的任务,返回保存其状态和结果的期货列表,当它们全部完成时。

因此,这两种策略基本上都是相同的,但是如果调用invokeAll(),则会被阻塞,直到所有任务都完成为止。

原文(不完整)答复:

invokeAll()方法正是在这种情况下存在的。你绝对应该用它。

不过,您并不需要实例化该List

代码语言:javascript
运行
复制
ExecutorService executorService = Executors.newFixedThreadPool(5);
List<Future<String>> futures = executorService.invokeAll(myCallableList));

这应该足够了,而且看起来比第一种选择要干净得多。

票数 7
EN

Stack Overflow用户

发布于 2017-04-11 10:21:27

假设您有一个任务,其结果取决于独立可执行任务的数量。但是要完成最初的任务,你只有有限的时间。就像API调用一样。

因此,例如,您有100 as的顶级任务要完成,还有10个依赖任务。为此,如果您在这里使用提交,代码将是什么样的。

代码语言:javascript
运行
复制
List<Callable> tasks = []// assume contains sub tasks
List<Future> futures = [] 
for(Callable task: tasks) {
   futures.add(service.submit(task));
}

for(Future futute: futures) {
    future.get(100, TimeUnit.MILLISECONDS);
}

因此,如果每个子任务都需要精确的50 ms来完成上面的代码,则需要50 ms。但是,如果每个子任务需要1000 ms才能完成上述任务,则需要100 * 10 = 1000 ms或1s。这使得计算所有子任务的总时间小于100 is变得困难。

在这种情况下,invokeAll方法可以帮助我们

代码语言:javascript
运行
复制
List<Futures> futures = service.invokeall(tasks, 100, TimeUnit.MILLISECONDS)
for(Future future: futures) {
   if(!future.isCancelled()) {
       results.add(future.get());
   }
}

这样,即使单个子任务花费的时间更多,最长的时间也是100 ms。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34440604

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档