英文:
ExecutorService.submit() vs ExecutorSerivce.invokeXyz()
问题
ExecutorService
包含以下方法:
invokeAll(Collection<? extends Callable<T>> tasks)
invokeAny(Collection<? extends Callable<T>> tasks)
submit(Callable<T> task)
我对术语submit
与invoke
的使用感到困惑。这是否意味着invokeXyz()
方法会立即通过底层线程池调用这些任务,而submit()
则对提交的任务进行某种调度。
这个回答说:“如果我们希望等待所有提交给ExecutorService的任务完成”。这里的“等待”是指什么?
英文:
ExecutorService
contains following methods:
invokeAll(Collection<? extends Callable<T>> tasks)
invokeAny(Collection<? extends Callable<T>> tasks)
submit(Callable<T> task)
I am confused about the use of terms submit
vs invoke
. Does it mean that invokeXyz()
methods invoke those tasks immediately as soon as possible by underlying thread pool and submit()
does some kind of scheduling of tasks submitted.
This answer says "if we want to wait for completion of all tasks, which have been submitted to ExecutorService". What does "wait for" here refers to?
答案1
得分: 2
`invoke..()`和`submit()`都会立即执行它们的任务(假设有线程可用于运行任务)。区别在于,`invoke...()`会等待在单独线程中运行的任务完成后再返回结果,而`submit()`会立即返回,意味着它执行的任务仍在另一个线程中运行。
换句话说,从`invokeAll()`返回的`Future`对象保证处于`Future.isDone() == true`的状态。而从`submit()`返回的`Future`对象可能处于`Future.isDone() == false`的状态。
我们可以很容易地演示时间差异。
public static void main(String... args) throws InterruptedException {
Callable<String> c1 = () -> { System.out.println("Hello "); return "Hello "; };
Callable<String> c2 = () -> { System.out.println("World!"); return "World!"; };
List<Callable<String>> callables = List.of(c1, c2);
ExecutorService executor = Executors.newSingleThreadExecutor();
System.out.println("Begin invokeAll...");
List<Future<String>> allFutures = executor.invokeAll(callables);
System.out.println("End invokeAll.\n");
System.out.println("Begin submit...");
List<Future<String>> submittedFutures = callables.stream().map(executor::submit).collect(toList());
System.out.println("End submit.");
}
结果是,`callables`会在`invokeAll()`方法完成之前打印出它们的Hello World消息;但是`callables`会在`submit()`方法完成之后才打印出Hello World。
/*
Begin invokeAll...
Hello
World!
End invokeAll.
Begin submit...
End submit.
Hello
World!
*/
您可以在IDE中对此代码进行调试,通过在`c1`或`c2`中添加一些`sleep()`时间,观察终端的输出。这应该会让您相信`invoke...()`确实会等待某些事情发生,但`submit()`则不会等待。
英文:
Both invoke..()
and submit()
will execute their tasks immediately (assuming threads are available to run the tasks). The difference is that invoke...()
will wait for the tasks running in separate threads to finish before returning a result, whereas submit()
will return immediately, meaning the task it executed is still running in another thread.
In other words, the Future
objects returned from invokeAll()
are guaranteed to be in a state where Future.isDone() == true
. The Future
object returned from submit()
can be in a state where Future.isDone() == false
.
We can easily demonstrate the timing difference.
public static void main(String... args) throws InterruptedException {
Callable<String> c1 = () -> { System.out.println("Hello "); return "Hello "; };
Callable<String> c2 = () -> { System.out.println("World!"); return "World!"; };
List<Callable<String>> callables = List.of(c1, c2);
ExecutorService executor = Executors.newSingleThreadExecutor();
System.out.println("Begin invokeAll...");
List<Future<String>> allFutures = executor.invokeAll(callables);
System.out.println("End invokeAll.\n");
System.out.println("Begin submit...");
List<Future<String>> submittedFutures = callables.stream().map(executor::submit).collect(toList());
System.out.println("End submit.");
}
And the result is that the callables
print their Hello World message before the invokeAll()
method completes; but the callables
print Hello World after the submit()
method completes.
/*
Begin invokeAll...
Hello
World!
End invokeAll.
Begin submit...
End submit.
Hello
World!
*/
You can play around with this code in an IDE by adding some sleep()
time in c1
or c2
and watching as the terminal prints out. This should convince you that invoke...()
does indeed wait for something to happen, but submit()
does not.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论