Производитель и потребитель могут общаться двумя способами: синхронно и асинхронно.
В синхронном (основанном на извлечении) потребителе является потоком и используется некоторый промежуточный объект коммуникатора. Обычно это очередь блокировки. В особом случае, когда в течение всего сеанса связи между производителем и потребителем передается только одно значение, может использоваться коммуникатор, который реализует интерфейс Future
. Этот способ называется синхронным, потому что потребитель вызывает вызывающий метод, такой как Future.get()
, и эти методы ждут, пока значение не станет доступным, а затем возвращают это значение в результате. То есть запрос значения и его получение запрограммированы в одном и том же операторе, хотя эти действия могут быть разделены во времени.
Недостаток синхронного обмена данными заключается в том, что когда потребитель ожидает запрошенного значения, он тратит значительный объем памяти для своего стека потоков. В результате мы можем иметь только ограниченное количество действий, которые ждут данных. Например, это могут быть интернет-соединения, обслуживающие нескольких клиентов. Чтобы увеличить это число, мы можем представить потребителя не как поток, а как некоторый относительно небольшой объект с методами, вызываемыми производителем или коммуникатором, когда данные для потребителя доступны. Этот способ называется асинхронным. Он разделен на 2 действия: запрос производителя на передачу данных и передачу этих данных потребителю. Это асинхронный (push-based) метод.
Теперь ответ на вопрос: Future
может выступать только в качестве синхронного коммуникатора (с методами get
), а Mono
может использоваться как в качестве синхронного коммуникатора (с методами block
), так и как асинхронный (с subscribe
методами).
Обратите внимание, что java.util.concurrent.CompletableFuture
может также действовать как синхронный и асинхронный коммуникатор. Зачем иметь похожие средства, чтобы делать то же самое? Это явление называется , а не изобретено здесь .