`ExecutorService.submit()` 与 `ExecutorService.invokeXyz()` 的区别。

huangapple go评论80阅读模式
英文:

ExecutorService.submit() vs ExecutorSerivce.invokeXyz()

问题

ExecutorService包含以下方法:

  • invokeAll(Collection<? extends Callable<T>> tasks)
  • invokeAny(Collection<? extends Callable<T>> tasks)
  • submit(Callable<T> task)

我对术语submitinvoke的使用感到困惑。这是否意味着invokeXyz()方法会立即通过底层线程池调用这些任务,而submit()则对提交的任务进行某种调度。

这个回答说:“如果我们希望等待所有提交给ExecutorService的任务完成”。这里的“等待”是指什么?

英文:

ExecutorService contains following methods:

  • invokeAll(Collection&lt;? extends Callable&lt;T&gt;&gt; tasks)
  • invokeAny(Collection&lt;? extends Callable&lt;T&gt;&gt; tasks)
  • submit(Callable&lt;T&gt; 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&lt;String&gt; c1 = () -&gt; { System.out.println(&quot;Hello &quot;); return &quot;Hello &quot;; };
    Callable&lt;String&gt; c2 = () -&gt; { System.out.println(&quot;World!&quot;); return &quot;World!&quot;; };
    List&lt;Callable&lt;String&gt;&gt; callables = List.of(c1, c2);
    ExecutorService executor = Executors.newSingleThreadExecutor();

    System.out.println(&quot;Begin invokeAll...&quot;);
    List&lt;Future&lt;String&gt;&gt; allFutures = executor.invokeAll(callables);
    System.out.println(&quot;End invokeAll.\n&quot;);

    System.out.println(&quot;Begin submit...&quot;);
    List&lt;Future&lt;String&gt;&gt; submittedFutures = callables.stream().map(executor::submit).collect(toList());
    System.out.println(&quot;End submit.&quot;);
}

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.

huangapple
  • 本文由 发表于 2020年4月6日 19:37:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/61058889.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定