В следующем коде имеет значение вызов thenRunAsync ? Может, мне просто позвонить thenRun вместо этого?
CompletableFuture.runAsync(this::doWork , executorService)
.thenRunAsync(this::handleSuccess);
Доработка в ответ на комментарии: Если бы я вместо этого использовал этот код,
CompletableFuture.runAsync(this::doWork , executorService)
.thenRun(this::handleSuccess);
будет ли он вести себя иначе?
В обоих случаях поведение неблокирующее, и вторая задача не запускается, пока не завершится первая, насколько я понимаю.
Метод thenRun
позволяет выполнять Runnable
непосредственно в потоке вызывающего, если CompletableFuture
он уже завершился. Поскольку даже в цепочке прямого вызова, например, CompletableFuture.runAsync(…).thenRun(…);
существует вероятность того, что асинхронная задача уже завершена к моменту thenRun
вызова, существует вероятность того, что зависимое действие выполняется в потоке вызывающего, в отличие от thenRunAsync
которого всегда будет использовать исполнитель по умолчанию (или предоставленный) .
Одним предложением, да, это имеет значение.
Между прочим, использование thenRunAsync
(версия с одним аргументом) не будет выполнять действие с использованием Executor
предоставленного для исходного вызова фабрики, но по умолчанию Executor
.
Вы можете легко сравнить различные варианты поведения:
public static void main(String[] args) {
ExecutorService e=Executors.newSingleThreadExecutor(r -> new Thread(r, "sole thread"));
CompletableFuture<?> f=CompletableFuture.runAsync(()->{}, e);
f.join();
f.thenRun(()->System.out.println("thenRun:\t"+Thread.currentThread()));
f.thenRunAsync(()->System.out.println("thenRunAsync:\t"+Thread.currentThread()));
f.thenRunAsync(()->System.out.println("thenRunAsync+e:\t"+Thread.currentThread()), e);
e.shutdown();
}
напечатает
thenRun: Thread[main,5,main]
thenRunAsync: Thread[ForkJoinPool.commonPool-worker-1,5,main]
thenRunAsync+e: Thread[sole thread,5,main]
в то время как
public static void main(String[] args) {
ExecutorService e=Executors.newSingleThreadExecutor(r -> new Thread(r, "sole thread"));
CompletableFuture<?>f=CompletableFuture.runAsync(()->LockSupport.parkNanos((int)1e9),e);
f.thenRun(()->System.out.println("thenRun:\t"+Thread.currentThread()));
f.thenRunAsync(()->System.out.println("thenRunAsync:\t"+Thread.currentThread()));
f.thenRunAsync(()->System.out.println("thenRunAsync+e:\t"+Thread.currentThread()), e);
LockSupport.parkNanos((int)2e9);
e.shutdown();
}
напечатает
thenRun: Thread[sole thread,5,main]
thenRunAsync: Thread[ForkJoinPool.commonPool-worker-1,5,main]
thenRunAsync+e: Thread[sole thread,5,main]
Таким образом, действие thenRun
может выполняться либо в потоке вызывающего, либо в потоке Executor
', тогда как один аргумент thenRunAsync
всегда будет использовать пул Fork / Join, и только два аргумента thenRunAsync
всегда будут использовать предоставленный исполнитель.
Эта статья взята из Интернета, укажите источник при перепечатке.
Если есть какие-либо нарушения, пожалуйста, свяжитесь с[email protected] Удалить.
я говорю два предложения