Функции ведут себя как командлеты. То есть вы не набираете dir (c: \ temp). Функции также принимают параметры как разделенные пробелы и как командлеты, поддерживают позиционные, именованные и необязательные параметры, например:
Greet Recardo 5
Greet -times 5 -name Ricardo
PowerShell использует (), чтобы вы могли указывать такие выражения:
function Greet([string[]]$names, [int]$times=5) {
foreach ($name in $names) {
1..$times | Foreach {"Hi $name"}
}
}
Greet Ricardo (1+4)
Great Ricardo # Note that $times defaults to 5
Вы также можете указать простые массивы с помощью списка, разделенного запятыми, например:
Greet Ricardo,Lucy,Ethyl (6-1)
Итак, когда вы передаете что-то вроде ("Ricardo",5)
, которое оценивается как одно значение параметра, которое представляет собой массив, содержащий два элемента "Ricardo"
и 5
. Это будет передано параметру $name
, но тогда не будет значения для параметра $times
.
Единственный раз, когда вы используете список параметров в скобках, является вызов методов .NET, например:
"Hello World".Substring(6, 3)
Наибольшее отличие состоит в том, что Mono<T>
может быть полностью ленивым, тогда как, когда вы получаете Future<T>
, базовая обработка уже началась.
При типичном холоде Mono
ничего не происходит, пока вы subscribe()
с ним не работаете, что позволяет обойти Mono
в приложении и попутно обогатить его операторами, прежде чем даже начать обработку.
Также гораздо проще сохранять асинхронность, используя Mono
по сравнению с Future
(где API имеет тенденцию заставлять вас вызывать блокировку get()
).
Наконец, по сравнению с Future
и CompletableFuture
, аспект композиции улучшен в Mono
с обширным словарем операторов, которые он предлагает.
Производитель и потребитель могут общаться двумя способами: синхронно и асинхронно.
В синхронном (основанном на извлечении) потребителе является потоком, и используется некоторый промежуточный объект коммуникатора. Обычно это очередь блокировки. В особом случае, когда во время всей связи производитель-потребитель передается только одно значение, может использоваться коммуникатор, который реализует интерфейс Future
. Этот способ называется синхронным, поскольку потребитель вызывает вызывающий метод, такой как Future.get()
, и эти методы ждут, когда значение станет доступным, а затем возвращаются с этим значением в качестве результата. То есть запрос значения и его получение запрограммированы в одном и том же выражении, хотя эти действия могут быть разделены во времени.
Недостаток синхронной связи заключается в том, что когда потребитель ожидает запрошенного значения, он тратит значительный объем памяти для своего стека потоков. В результате мы можем иметь только ограниченное количество действий, которые ждут данных. Например, это могут быть интернет-соединения, обслуживающие нескольких клиентов. Чтобы увеличить это число, мы можем представить потребителя не как поток, а как некоторый относительно небольшой объект с методами, вызываемыми производителем или коммуникатором, когда данные для потребителя доступны. Этот способ называется асинхронным. Он разделен на 2 действия: запрос производителя на передачу данных и передачу этих данных потребителю. Это асинхронный (push-based) метод.
Теперь ответ на вопрос: Future
может выступать только в качестве синхронного коммуникатора (с методами get
), а Mono
может использоваться как в качестве синхронного коммуникатора (с методами block
), так и как асинхронный (с subscribe
методами).
Обратите внимание, что java.util.concurrent.CompletableFuture
также может действовать как синхронный и асинхронный коммуникатор. Зачем иметь похожие средства, чтобы делать то же самое? Это явление называется , а не изобретено здесь .