Асинхронный CompletableFuture. Часть 1
Время от времени появляется необходимость выполнить асинхронно (т.е. одновременно с основным действием программы выполняется другая задача) какой-нибудь код. Например, отправить письмо по e-mail или что-нибудь из базы данных прочитать. В Java для подобных операций можно создать поток и выполнить в нём нужное действие.
private void simpleRun() throws ExecutionException, InterruptedException { final CompletableFuture<String> future = new CompletableFuture<>(); new Thread( () -> { System.out.println("job started"); sleep(3); future.complete("feature done"); System.out.println("job done"); }).start(); System.out.println("waiting..."); String result = future.get(); System.out.println("finished, result:" + result); }
Что здесь происходит?
Просто создаётся поток и имитируется задача длительностью 3 сек.: вызов Thread.sleep(TimeUnit.SECONDS.toMillis(sec)); с перехваченным исключением. Задача возвращает результат через CompletableFuture.
Это вполне рабочий вариант, но можно сделать заметно проще:
private void asyncRun() throws ExecutionException, InterruptedException { final CompletableFuture<String> future = CompletableFuture.supplyAsync(()-> { System.out.println("job started"); sleep(3); System.out.println("job done"); return "feature done"; }); System.out.println("waiting..."); String result = future.get(); System.out.println("finished, result:" + result); }
В этом коде используется интересная возможность CompletableFuture из пакета java.util.concurrent. CompletableFuture «умеет» запускать код в параллельном потоке, и при этом использует встроенный thread pool. Его использование упрощает код и даёт прирост в производительности приложения.
Ведь на создание нового потока не расходуются системные ресурсы. Более того, встроенный thread pool уже оптимизирован и работает эффективнее большинства пулов, созданных пользователем.
Однако надо помнить и об ограничениях. Например, разные модули программы могут конкурировать за потоки из общего пула, что может привести к дополнительным ожиданиям.
В следующей заметке мы рассмотрим другие интересные возможности CompletableFuture из пакета java.util.concurrent.
Есть вопрос? Напишите в комментариях!