В (Java) реактивном программировании, в чем разница между Future<T>
и (Project Reactor) Mono<T>
? Оба кажутся средствами для доступа к результату асинхронного вычисления в момент в будущем, когда вычисление будет завершено. Зачем вводить интерфейс Mono
, если Future
уже выполняет свою работу?
Разница между будущим и моно
- Возможно, это поможет: spring.io/blog/2016/04/19/ понимающие-реактивные-типы (первый результат для java reactive mono по сравнению с будущим). 17.01.2019
Ответы:
Самая большая разница в том, что Mono<T>
может быть полностью ленивым, тогда как когда вы получаете Future<T>
, базовая обработка уже началась.
С типичным холодным Mono
ничего не происходит до тех пор, пока вы subscribe()
к нему не присоединитесь, что позволяет передавать Mono
по всему приложению и попутно обогащать его операторами, еще до начала обработки.
Также гораздо проще поддерживать асинхронность с помощью Mono
по сравнению с Future
(где API имеет тенденцию заставлять вас вызывать блокировку get()
).
Наконец, по сравнению с Future
и CompletableFuture
аспект композиции улучшен в Mono
благодаря расширенному словарю операторов, которые он предлагает.
Производитель и потребитель могут общаться двумя способами: синхронно и асинхронно.
В синхронном (вытягивающем) способе потребителем является поток, и используется некоторый промежуточный объект-коммуникатор. Обычно это блокирующая очередь. В особом случае, когда во время всего взаимодействия производитель-потребитель передается только одно значение, может использоваться коммуникатор, который реализует интерфейс Future
. Этот способ называется синхронным, потому что потребитель вызывает метод связи, такой как Future.get()
, и эти методы ждут, пока значение не станет доступным, а затем возвращает это значение в качестве результата. То есть запрос значения и его получение программируются в одном операторе, хотя эти действия могут быть разделены во времени.
Недостатком синхронной связи является то, что когда потребитель ожидает запрошенное значение, он тратит впустую значительный объем памяти для своего стека потока. В результате у нас может быть только ограниченное количество действий, ожидающих данных. Например, это могут быть интернет-соединения, обслуживающие несколько клиентов. Чтобы увеличить это число, мы можем представить потребителя не как поток, а как некоторый относительно небольшой объект с методами, вызываемыми производителем или коммуникатором, когда доступны данные для потребителя. Такой способ называется асинхронным. Он разделен на 2 действия: запрос к производителю на передачу данных и передача этих данных потребителю. Это асинхронный (на основе push) метод.
Теперь ответ на вопрос: Future
может работать только как синхронный коммуникатор (с get
методами), а Mono
может использоваться как синхронный коммуникатор (с block
методами), так и как асинхронный (с subscribe
методами).
Обратите внимание, что java.util.concurrent.CompletableFuture
также может действовать как синхронный и асинхронный коммуникатор. Зачем иметь одинаковые средства, чтобы делать одно и то же? Этот феномен называется здесь не придуман.
Future
, который поддерживает методsubscribe
, с именем, которое означает что-то более значимое, чем 1 или Monkey. 01.10.2020