ParallelFlux против flatMap () для задачи блокировки ввода-вывода

У меня есть цепочка Project Reactor, которая включает задачу блокировки (сетевой вызов, нам нужно дождаться ответа). Я хочу одновременно запускать несколько блокирующих задач.

Похоже, что можно использовать ParallelFlux или flatMap (), простые примеры:

Flux.just(1)
    .repeat(10)
    .parallel(3)
    .runOn(Schedulers.elastic())
    .doOnNext(i -> blockingTask())
    .sequential()
    .subscribe()

or

Flux.just(1)
    .repeat(10)
    .flatMap(i -> Mono.fromCallable(() -> {blockingTask(); return i;}).subscribeOn(Schedulers.elastic()), 3)
    .subscribe();

В чем достоинства двух техник? Одно предпочтительнее другого? Есть ли альтернативы?


person Corin Fletcher    schedule 07.04.2017    source источник


Ответы (1)


parallel предназначен для распараллеливания задач в целях повышения производительности и распределения работы между «рельсами» или «группами», каждая из которых получает свой собственный контекст выполнения из Scheduler, который вы передаете runOn. Короче говоря, он заставит работать все ядра вашего процессора, если вы выполняете интенсивную работу с процессором. Но вы выполняете работу, связанную с вводом-выводом ...

Так что в вашем случае flatMap - лучший кандидат. Использование flatMap для распараллеливания больше связано с оркестровкой.

Это в значительной степени две альтернативы, если не учитывать немного другой вкус flatMap, которым является flatMapSequential (concatMap на самом деле не допускает распараллеливания).

person Simon Baslé    schedule 07.04.2017
comment
Я действительно не вижу разницы. С flatMap вам все равно придется подписываться на разные темы - person IceMan; 07.05.2018
comment
Да, я согласен с @IceMan. Каким образом flatMap обеспечивает распараллеливание без подписки на подписку (планировщик)? - person Vivek Sethi; 23.12.2019
comment
Я полагаю, вы упустили .subscribeOn(Schedulers.elastic()), 3) - на самом деле, в приведенном примере он находится в той же строке, где находится flatMap. И я согласен, это легко упустить из виду, поскольку все остальные операторы находятся на отдельных строках. - person barthand; 31.01.2021
comment
согласен, с примером блокировки разницу трудно увидеть. но если источник (и), с которым работает flatMap, неблокирующий (ввод-вывод является основным кандидатом для преобразования в неблокирующую реализацию), тогда flatMap может действительно проявить себя. оператор будет действовать как цикл событий, получая уведомление от издателя ввода-вывода, когда он будет готов, и обеспечивая последовательную публикацию всех этих элементов в нисходящем потоке - person Simon Baslé; 02.02.2021