ExecutorService vs CompletableFuture - PullRequest
       58

ExecutorService vs CompletableFuture

0 голосов
/ 13 сентября 2018

Я пытался реализовать асинхронный процесс, где родительский метод вызывает дочерний метод, который, в свою очередь, вызывает три разных метода. Я хочу, чтобы весь этот процесс выполнялся асинхронно, то есть после того, как эти три вызова в дочернем методе будут выполнены параллельно, элемент управления должен вернуться к родительскому методу и продолжить выполнение до конца.

У меня есть этот код, который при тестировании работает нормально.

public ReturnSomething parent(){
    child();
    ...//rest to UI
}

private void child(){
  ExecutorService executorService = Executors.newFixedThreadPool(3);

  Runnable service1 = () -> {
     MyFileService.service1();
  };

  Runnable service2 = () -> {
      MyFileService.service2();
  };

  Runnable service3 = () -> {
      MyFileService.service3();
  };

  executorService.submit(service1);
  executorService.submit(service2);
  executorService.submit(service3);
}

Теперь, мое руководство просит меня скорее использовать это.

public ReturnSomething parent(){
    child();
    ...//rest to UI
}

private void child(){
    CompletableFuture.supplyAsync(() ->  MyFileService.service1();
    CompletableFuture.supplyAsync(() ->  MyFileService.service2();
    CompletableFuture.supplyAsync(() ->  MyFileService.service3();
}

Я понимаю, что это CompletableFuture является новинкой в ​​Java 8, но чем второй код лучше первого? Поскольку для ExecutorService я не вызываю метод "get ()", я не буду ждать ответа aysnc. Итак, кто-нибудь может объяснить, в чем разница?

Ответы [ 3 ]

0 голосов
/ 13 сентября 2018

Прежде всего, последнее улучшает читабельность. Во-вторых, я не уверен, что вы спешили (чтобы объяснить вашу проблему в общих чертах), что вы создали новый экземпляр ExecutorService каждый раз, когда parent () делает вызов child ().

В противном случае CompletableFuture.supplyAsync возвращает гораздо более удобный способ получить ссылку на общий общий пул, который облегчит вашу жизнь, если вы не хотите вносить конкретные изменения в способ, которым потоки в пуле должны обслуживать ваш запрос.

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html#commonPool--

0 голосов
/ 13 сентября 2018

Функционально два подхода более или менее одинаковы:

  • Вы отправляете свои задачи на выполнение;
  • Вы не ждете результата.

Технически, однако, есть некоторые тонкие различия:

  • Во втором подходе вы не указали исполнителя, поэтому он будет использовать общий ForkJoinPool. Вам нужно будет передать исполнителя в качестве второго аргумента supplyAsync(), если вы этого не хотите;
  • API CompletableFuture позволяет легко объединять больше вызовов с помощью thenApply(), thenCompose() и т. Д. Таким образом, он более гибкий, чем простой Future, возвращаемый ExecutorService.submit();
  • Использование CompletableFuture позволяет легко вернуть будущее из вашего child() метода, используя return CompletableFuture.allOf(the previously created futures).

Что касается читабельности, это вопрос предпочтений, но если вам нужен эквивалентный код, подход CompletableFuture может считаться менее читабельным, если вы отформатировали его аналогичным образом. Для сравнения:

executorService.submit(MyFileService::service1);
executorService.submit(MyFileService::service2);
executorService.submit(MyFileService::service3);

с

CompletableFuture.supplyAsync(MyFileService::service1, executorService);
CompletableFuture.supplyAsync(MyFileService::service2, executorService);
CompletableFuture.supplyAsync(MyFileService::service3, executorService);
0 голосов
/ 13 сентября 2018

Вы не ждете результатов в обоих случаях.

Преимущество второго подхода состоит в том, что он просто меньше шаблонного. Вот для чего хороши runAsync() и supplyAsync().

Но если вы на самом деле не возвращаете никакого значения, вы должны использовать runAsync()

То, что также дает второй подход, - это возможность ждать все фьючерсы с CompletableFuture.allOf(). Которого также не существует в первом сценарии.

...