Асинхронность и реактивность в Java: CompletableFuture, Flow и Virtual Threads

Асинхронность и реактивность в Java: CompletableFuture, Flow и Virtual Threads

В современном Java-разработке есть три основных подхода к асинхронности и параллельности:

  • CompletableFuture — для одиночных асинхронных задач.
  • Flow / Reactive Streams — для потоков данных с контролем скорости (backpressure).
  • Virtual Threads / Loom — для масштабируемой параллельности без блокировок.

Образное понимание

Flow — это «река данных с контролем течения».
Virtual Threads — это «миллионы работников», которые готовы обрабатывать данные в своей скорости, но не умеют замедлять реку.
CompletableFuture — это «единичный груз», который доставляется асинхронно.

Сравнение подходов

Механизм Сильная сторона Когда использовать
CompletableFuture (Java 8) Простая асинхронность для одиночных задач, цепочки действий API-запросы, DB, файловые операции
Flow / Reactive Streams (Java 9) Поток данных с контролем скорости (backpressure), пайплайны обработки событий Стриминг, брокеры сообщений, WebFlux, event-driven системы
Virtual Threads / Loom (Java 21) Массовая параллельность без блокировок, линейный код Web-серверы, API, масштабируемые сервисы

Примеры кода

1. CompletableFuture — одиночная асинхронная задача


import java.util.concurrent.*;

public class CompletableFutureExample {
    public static void main(String[] args) throws Exception {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            sleep(500);
            return "Hello from CompletableFuture";
        });

        future.thenAccept(System.out::println);

        Thread.sleep(1000);
    }

    private static void sleep(long ms) {
        try { Thread.sleep(ms); } catch (InterruptedException e) {}
    }
}
    

2. Flow — поток данных с backpressure


import java.util.concurrent.Flow.*;
import java.util.concurrent.SubmissionPublisher;

public class FlowExample {
    public static void main(String[] args) throws Exception {
        SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();

        Subscriber<Integer> subscriber = new Subscriber<>() {
            private Subscription subscription;

            @Override
            public void onSubscribe(Subscription subscription) {
                this.subscription = subscription;
                subscription.request(5);
            }

            @Override
            public void onNext(Integer item) {
                System.out.println("Received: " + item);
                sleep(200);
            }

            @Override
            public void onError(Throwable throwable) { throwable.printStackTrace(); }

            @Override
            public void onComplete() { System.out.println("Done!"); }
        };

        publisher.subscribe(subscriber);

        for (int i = 1; i <= 10; i++) publisher.submit(i);

        publisher.close();
        Thread.sleep(3000);
    }

    private static void sleep(long ms) {
        try { Thread.sleep(ms); } catch (InterruptedException e) {}
    }
}
    

3. Virtual Threads — миллионы параллельных задач (Java 21+)


public class VirtualThreadsExample {
    public static void main(String[] args) throws Exception {
        for (int i = 1; i <= 10; i++) {
            Thread.startVirtualThread(() -> {
                System.out.println("Hello from virtual thread " + Thread.currentThread().getName());
                sleep(200);
            });
        }

        Thread.sleep(1000);
    }

    private static void sleep(long ms) {
        try { Thread.sleep(ms); } catch (InterruptedException e) {}
    }
}
    
 
Flow (река данных)
[Publisher] --> [Subscriber] --> [Subscriber]
   ^ контроль скорости (backpressure)



Virtual Threads (работники)
[Task1] [Task2] [Task3] ... [TaskN]
каждый работает в своей скорости, никто не тормозит


CompletableFuture — одиночный груз
Async Task  ---> Result
          \
           ---> thenAccept / thenApply

Когда коллбеки нужны


CompletableFuture  -> коллбеки почти всегда
Flow               -> коллбеки через onNext/onComplete
Virtual Threads    -> коллбеки почти не нужны

Вывод

Каждая модель асинхронности имеет свою силу и применяется для разных бизнес-задач:

  • CompletableFuture — для единичных задач, где важна простота.
  • Flow — для потоков данных с контролем скорости, где важна надежность и backpressure.
  • Virtual Threads — для масштабируемых серверов, где важна читаемость и параллельность без коллбеков.

Всего лайков: 0
Мой канал в социальных сетях
Отправляя email, вы принимаете условия политики конфиденциальности

Полезные статьи:

Как удержать легаси-проект от смерти и подарить ему ещё 10 лет
Признаки легаси-проекта: как распознать старый корабль Легаси — это не просто старый код. Это живой организм, который пережил десятки изменений, смену команд, устаревшие технологии и множество временн...
Как написать Hello World в Java. Что такое Statement. Как писать Комментарии Java
Сегодня мы разберем основные элементы Java: Statement (инструкции) Блоки кода Создадим простейшую программу Hello World! Разберем каждое слово в коде Научимся писать комментарии, которые не исполняют...
Современный подход к параллелизму в Java - Fork/Join Framework, CompletableFuture и виртуальные потоки (Project Loom)
Предисловие Мир программного обеспечения уже давно перестал быть спокойным океаном: сегодня это бурная экосистема, где каждая миллисекунда отклика приложения может стоить компании клиентов, репутации ...

Новые статьи:

Java под микроскопом: стек, куча и GC на примере кода
Схема - Java Memory Model - Heap / Non-Heap / Stack Heap (память для объектов) Создаёт объекты через new. Young Generation: Eden + Survivor. Old Generation: объекты, пережившие несколько сборок G...
Как удержать легаси-проект от смерти и подарить ему ещё 10 лет
Признаки легаси-проекта: как распознать старый корабль Легаси — это не просто старый код. Это живой организм, который пережил десятки изменений, смену команд, устаревшие технологии и множество временн...
Асинхронность и реактивность в Java: CompletableFuture, Flow и Virtual Threads
В современном Java-разработке есть три основных подхода к асинхронности и параллельности: CompletableFuture — для одиночных асинхронных задач. Flow / Reactive Streams — для потоков данных с контролем...
Fullscreen image