[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-mnogopotochnost-chto-takoe-reaktivnye-potoki-i-java-util-concurrent-flow-api":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":22,"progress":23,"seo":24},304,"chto-takoe-reaktivnye-potoki-i-java-util-concurrent-flow-api",8,"mnogopotochnost","Многопоточность","🔀","Что такое реактивные потоки и java.util.concurrent.Flow API?","\u003C!-- grade: 5\u002F5 — подробный ответ с backpressure, примерами и связью с библиотеками -->\n\n**Реактивные потоки (Reactive Streams)** — это стандарт асинхронной обработки потоков данных с неблокирующим **обратным давлением (backpressure)**. Начиная с Java 9, стандарт включён в JDK через класс `java.util.concurrent.Flow`.\n\n**Основные интерфейсы Flow:**\n\n```java\n\u002F\u002F Publisher — источник данных\npublic interface Publisher\u003CT> {\n    void subscribe(Subscriber\u003C? super T> subscriber);\n}\n\n\u002F\u002F Subscriber — потребитель данных\npublic interface Subscriber\u003CT> {\n    void onSubscribe(Subscription subscription);  \u002F\u002F При подписке\n    void onNext(T item);                           \u002F\u002F Следующий элемент\n    void onError(Throwable throwable);             \u002F\u002F Ошибка\n    void onComplete();                             \u002F\u002F Завершение потока\n}\n\n\u002F\u002F Subscription — связь Publisher и Subscriber\npublic interface Subscription {\n    void request(long n);  \u002F\u002F Запрос n элементов (backpressure!)\n    void cancel();         \u002F\u002F Отмена подписки\n}\n\n\u002F\u002F Processor — одновременно Publisher и Subscriber\npublic interface Processor\u003CT, R> extends Subscriber\u003CT>, Publisher\u003CR> {\n}\n```\n\n**Механизм обратного давления (backpressure):**\n\nBackpressure решает проблему, когда производитель генерирует данные быстрее потребителя. Потребитель явно запрашивает количество элементов через `subscription.request(n)`, и производитель отправляет не более n элементов.\n\n\u003Cdetails>\n\u003Csummary>Код: пример с SubmissionPublisher\u003C\u002Fsummary>\n\n```java\ntry (SubmissionPublisher\u003CString> publisher = new SubmissionPublisher\u003C>()) {\n    publisher.subscribe(new Flow.Subscriber\u003C>() {\n        private Flow.Subscription subscription;\n\n        @Override\n        public void onSubscribe(Flow.Subscription subscription) {\n            this.subscription = subscription;\n            subscription.request(1); \u002F\u002F Запрашиваем первый элемент\n        }\n\n        @Override\n        public void onNext(String item) {\n            System.out.println(\"Получено: \" + item);\n            subscription.request(1); \u002F\u002F Запрашиваем следующий\n        }\n\n        @Override\n        public void onError(Throwable throwable) {\n            System.err.println(\"Ошибка: \" + throwable.getMessage());\n        }\n\n        @Override\n        public void onComplete() {\n            System.out.println(\"Поток завершён\");\n        }\n    });\n\n    List.of(\"Один\", \"Два\", \"Три\").forEach(publisher::submit);\n}\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Код: Processor для трансформации данных\u003C\u002Fsummary>\n\n```java\nclass TransformProcessor extends SubmissionPublisher\u003CString>\n        implements Flow.Processor\u003CString, String> {\n\n    private Flow.Subscription subscription;\n    private final Function\u003CString, String> transform;\n\n    TransformProcessor(Function\u003CString, String> transform) {\n        this.transform = transform;\n    }\n\n    @Override\n    public void onSubscribe(Flow.Subscription subscription) {\n        this.subscription = subscription;\n        subscription.request(1);\n    }\n\n    @Override\n    public void onNext(String item) {\n        submit(transform.apply(item)); \u002F\u002F Трансформируем и передаём дальше\n        subscription.request(1);\n    }\n\n    @Override\n    public void onError(Throwable throwable) { closeExceptionally(throwable); }\n\n    @Override\n    public void onComplete() { close(); }\n}\n```\n\n\u003C\u002Fdetails>\n\n**Связь с реактивными библиотеками:**\n\n`Flow` API — это только интерфейсы (стандарт совместимости). Для полноценной реактивной разработки используются библиотеки:\n\n| Библиотека | Основные типы | Применение |\n|---|---|---|\n| Project Reactor | `Mono`, `Flux` | Spring WebFlux |\n| RxJava | `Observable`, `Flowable` | Android, backend |\n| Mutiny | `Uni`, `Multi` | Quarkus |\n\nВсе библиотеки совместимы с `Flow` API через адаптеры.\n\n**Ключевые моменты:**\n- `SubmissionPublisher` — единственная встроенная реализация `Publisher` в JDK.\n- Backpressure — ключевая концепция: без него быстрый производитель вызовет `OutOfMemoryError`.\n- `onNext()` вызывается асинхронно — в потоке из пула `SubmissionPublisher`.\n\n**Частые ошибки:**\n- `subscription.request(Long.MAX_VALUE)` — отключает backpressure, переполнение буферов.\n- Блокирующие операции в `onNext()` — нарушает контракт реактивных потоков.\n- Забытый `subscription.request()` — поток «зависнет», `onNext()` никогда не будет вызван.\n\n**Актуальность:** реактивный подход остаётся стандартом для стриминга данных (Kafka, WebSocket, SSE). С Virtual Threads часть IO-bound сценариев решается проще через блокирующий код.\n\n> **Аналогия:** реактивные потоки — это конвейерная лента суши. Повар (Publisher) кладёт блюда, гость (Subscriber) берёт по одному. Если гость не успевает — конвейер замедляется (backpressure). Без backpressure блюда падают на пол (OOM).\n\n> **На собеседовании** ключевой вопрос: «Зачем нужен backpressure?» Ответ: без него при несоответствии скоростей Producer и Consumer буферы переполняются. Backpressure позволяет Subscriber контролировать скорость получения данных.","","senior",[15,16,17,18,19,20,21],"Flow-API","backpressure","SubmissionPublisher","Subscriber","Reactive-Streams","Publisher","concurrency",[],null,{"title":25,"description":26,"ogTitle":27,"ogDescription":28,"keywords":29,"schemaAnswer":34,"featuredSnippetReady":35},"Реактивные потоки и Flow API в Java — backpressure и Publisher-Subscriber — Gymterview","Reactive Streams — стандарт асинхронной обработки потоков данных с backpressure. Java 9 Flow API: Publisher, Subscriber, Subscription, Processor. SubmissionPublisher.","Flow API — реактивные потоки с backpressure в Java","Flow API (Java 9) определяет Publisher, Subscriber, Subscription, Processor. Backpressure через request(n). SubmissionPublisher — встроенная реализация.",[30,31,16,32,17,33],"Reactive Streams Java","Flow API","Publisher Subscriber","реактивные потоки","Reactive Streams — стандарт асинхронной обработки данных с неблокирующим backpressure. Java 9 включает стандарт через java.util.concurrent.Flow с четырьмя интерфейсами: Publisher (источник), Subscriber (потребитель с onSubscribe\u002FonNext\u002FonError\u002FonComplete), Subscription (связь с request(n) для backpressure и cancel()), Processor (промежуточный обработчик). SubmissionPublisher — встроенная реализация Publisher. Flow API — стандарт совместимости, для полноценной работы используют Reactor или RxJava.",true]