Ответ
В Java-сервисах асинхронное взаимодействие реализуется несколькими основными способами:
1. CompletableFuture (Java 8+) Используется для представления отложенного результата и построения цепочек асинхронных операций.
CompletableFuture.supplyAsync(() -> fetchDataFromService())
.thenApply(data -> transform(data))
.thenAccept(result -> System.out.println("Результат: " + result))
.exceptionally(ex -> {
System.err.println("Ошибка: " + ex.getMessage());
return null;
});
2. Реактивные библиотеки (Project Reactor, RxJava) Основаны на спецификации Reactive Streams и предоставляют мощный API для неблокирующей обработки потоков данных.
// Spring WebFlux с Project Reactor
@GetMapping("/data")
public Mono<ResponseEntity<String>> getData() {
return webClient.get()
.uri("/internal-service/api")
.retrieve()
.bodyToMono(String.class)
.map(body -> ResponseEntity.ok(body))
.onErrorResume(e -> Mono.just(ResponseEntity.status(500).build()));
}
3. Асинхронные сервлеты (Servlet 3.0+) Позволяют освобождать поток контейнера во время длительных операций.
@WebServlet(asyncSupported = true)
public class AsyncServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
AsyncContext asyncContext = req.startAsync();
CompletableFuture.runAsync(() -> {
// Длительная обработка
asyncContext.getResponse().getWriter().write("Готово");
asyncContext.complete();
});
}
}
Практические рекомендации:
- Используйте CompletableFuture для простых асинхронных задач внутри приложения
- Выбирайте реактивный стек (WebFlux) для высоконагруженных систем с большим количеством одновременных соединений
- Асинхронные сервлеты подходят для постепенной миграции legacy-кода
- Для межсервисного взаимодействия предпочтительны неблокирующие клиенты (WebClient, асинхронный RestTemplate)