1. Метод sendAsync()

Також за допомогою HttpClient можна надсилати асинхронні запити. Зазвичай це роблять у трьох випадках.

Перший випадок – це якщо запит буде виконуватися дуже довго, наприклад, надсилання/отримання файлу. Тоді цю операцію запускають та виконують асинхронно.

Другий випадок – тобі потрібно надсилати запити дуже часто, і ти не хочеш чекати відповіді від попереднього запиту перед надсиланням наступного.

І, нарешті, третій випадок – тобі не важливий результат твого запиту. Наприклад, ти раз на хвилину робиш скріншот свого екрана та надсилаєш його на сервер. Тобто логіка твоєї програми передбачає, що запитів багато, і доходять не всі з них. Тоді зручно працювати за принципом: надіслав і забув.

Щоб надіслати асинхронний запит, потрібно викликати метод sendAsync() в об'єкта класу HttpClient. Цей метод миттєво завершує роботу та повертає об'єкт CompletableFuture<HttpResponse>. З його допомогою можна відстежити, коли запит реально виконається, і навіть виконати певний код після завершення запиту. Приклад:


HttpClient client = HttpClient.newBuilder().build();
 
CompletableFuture<HttpResponse<String>> response = client.sendAsync(
        request,
        HttpResponse.BodyHandlers.ofString()
);

Метод sendAsync() повертає об'єкт CompletableFuture, що містить HttpResponse, що містить рядок, який поверне сервер.

2. Метод executor(), ExecutorService

Також HttpClient дозволяє передати до нього ExecutorService (пул потоків), які використовуються для виконання асинхронних запитів. Власне, в серверних Java-застосунках так і роблять.

Адже якщо на кожен запит до твого API ти будеш запускати кілька асинхронних запитів ще кудись, тобі жодних потоків не вистачить. Приклад:


ExecutorService executorService = Executors.newFixedThreadPool(2);
 
CompletableFuture<HttpResponse<String>> response1 = HttpClient.newBuilder()
  .executor(executorService)
  .build()
  .sendAsync(request, HttpResponse.BodyHandlers.ofString());
 
CompletableFuture<HttpResponse<String>> response2 = HttpClient.newBuilder()
  .executor(executorService)
  .build()
  .sendAsync(request, HttpResponse.BodyHandlers.ofString());

Якщо пул потоків не вказано, за замовчуванням використовується java.util.concurrent.Executors.newCachedThreadPool().