Elixir语言中 Task.async_stream 相关用法介绍如下。
用法一
async_stream(enumerable, fun, options \\ [])
(从 1.4.0 开始)
@spec async_stream(Enumerable.t(), (term() -> term()), keyword()) :: Enumerable.t()
返回在 enumerable 中的每个元素上同时运行给定函数 fun 的流。
与 工作方式相同,但使用匿名函数而不是 module-function-arguments 元组。 async_stream/5 fun 必须是 one-arity 匿名函数。
每个 enumerable 元素作为参数传递给给定的函数 fun 并由其自己的任务处理。任务将链接到调用者进程,类似于 。async/1
示例
异步计算每个字符串中的代码点,然后使用 reduce 将计数相加。
iex> strings = ["long string", "longer string", "there are many of these"]
iex> stream = Task.async_stream(strings, fn text -> text |> String.codepoints() |> Enum.count() end)
iex> Enum.reduce(stream, 0, fn {:ok, num}, acc -> num + acc end)
47
有关讨论、选项和更多示例,请参阅 。async_stream/5
用法二
async_stream(enumerable, module, function_name, args, options \\ [])
(从 1.4.0 开始)
@spec async_stream(Enumerable.t(), module(), atom(), [term()], keyword()) ::
Enumerable.t()
返回一个流,其中给定函数(module 和 function_name)同时映射到 enumerable 中的每个元素上。
enumerable 的每个元素都将附加到给定的 args 并由其自己的任务处理。这些任务将链接到一个中间流程,然后该流程链接到调用者流程。这意味着任务中的失败会终止调用者进程,而调用者进程中的失败会终止所有任务。
流式传输时,每个任务将在成功完成时发出{:ok, value},如果调用者正在捕获退出,则发出{:exit, reason}。结果的顺序取决于:ordered 选项的值。
并发级别和允许任务运行的时间可以通过选项来控制(参见下面的"Options" 部分)。
考虑使用 在主管下启动任务。如果您发现自己捕获出口以确保任务中的错误不会终止调用者进程,请考虑使用Task.Supervisor.async_stream/6 来启动未链接到调用者进程的任务。Task.Supervisor.async_stream_nolink/6
选项
-
:max_concurrency- 设置同时运行的最大任务数。默认为。System.schedulers_online/0 -
:ordered- 结果是否应以与输入流相同的顺序返回。当输出被排序时,Elixir 可能需要缓冲结果以按原始顺序发出它们。将此选项设置为 false 将禁用以删除排序为代价进行缓冲的需要。当您仅将任务用于副作用时,这也很有用。请注意,无论:ordered设置为什么,任务都将异步处理。如果您需要按顺序处理元素,请考虑改用或Enum.map/2。默认为Enum.each/2true。 -
:timeout- 每个任务允许执行的最长时间(以毫秒或:infinity为单位)。默认为5000。 -
:on_timeout- 任务超时时该怎么做。可能的值是::exit(默认)- 调用者(产生任务的进程)退出。:kill_task- 超时的任务被杀死。为该任务发出的值是{:exit, :timeout}。
示例
让我们构建一个流,然后枚举它:
stream = Task.async_stream(collection, Mod, :expensive_fun, [])
Enum.to_list(stream)
可以使用:max_concurrency 选项增加或减少并发性。例如,如果任务 IO 很重,则可以增加该值:
max_concurrency = System.schedulers_online() * 2
stream = Task.async_stream(collection, Mod, :expensive_fun, [], max_concurrency: max_concurrency)
Enum.to_list(stream)
如果您不关心计算结果,可以使用 运行流。还要设置 Stream.run/1 ordered: false ,因为您也不关心结果的顺序:
stream = Task.async_stream(collection, Mod, :expensive_fun, [], ordered: false)
Stream.run(stream)
第一个要完成的异步任务
也可以使用 执行M个任务,找到N个任务完成。例如:async_stream/3
[
&heavy_call_1/0,
&heavy_call_2/0,
&heavy_call_3/0
]
|> Task.async_stream(fn fun -> fun.() end, ordered: false, max_concurrency: 3)
|> Stream.filter(&match?({:ok, _}, &1))
|> Enum.take(2)
在上面的示例中,我们正在执行三个任务并等待前两个任务完成。我们使用 将自己限制为仅成功完成的任务,然后使用Stream.filter/2 检索N 个项目。请注意,设置 Enum.take/2 ordered: false 和 max_concurrency: M 很重要,其中 M 是任务数,以确保所有调用同时执行。
注意:未绑定 async + take
如果您想潜在地处理大量项目并仅保留部分结果,则可以end-up 处理比预期更多的项目。让我们看一个例子:
1..100
|> Task.async_stream(fn i ->
Process.sleep(100)
IO.puts(to_string(i))
end)
|> Enum.take(10)
在具有 8 个内核的机器上运行上面的示例将处理 16 个项目,即使您只需要 10 个元素,因为 同时处理项目。那是因为它将一次处理 8 个元素。然后所有 8 个元素大致同时完成,导致 8 个元素被启动以进行处理。在这额外的 8 个中,只有 2 个将被使用,其余的将被终止。async_stream/3
根据问题,您可以预先过滤或限制元素的数量:
1..100
|> Stream.take(10)
|> Task.async_stream(fn i ->
Process.sleep(100)
IO.puts(to_string(i))
end)
|> Enum.to_list()
在其他情况下,您可能需要调整 :max_concurrency 以限制有多少元素可能被过度处理,但会降低并发性。您还可以将要采用的元素数设置为 :max_concurrency 的倍数。例如,在上面的示例中设置max_concurrency: 5。
相关用法
- Elixir Task.async用法及代码示例
- Elixir Task.await_many用法及代码示例
- Elixir Task.await用法及代码示例
- Elixir Task.yield_many用法及代码示例
- Elixir Task.Supervisor.async_stream用法及代码示例
- Elixir Task.Supervisor用法及代码示例
- Elixir Task.completed用法及代码示例
- Elixir Task.Supervisor.start_child用法及代码示例
- Elixir Task.yield用法及代码示例
- Elixir Task.Supervisor.async_nolink用法及代码示例
- Elixir Task.Supervisor.start_link用法及代码示例
- Elixir Task用法及代码示例
- Elixir Time.add用法及代码示例
- Elixir Time.new用法及代码示例
- Elixir Tuple.duplicate用法及代码示例
- Elixir Time.to_erl用法及代码示例
- Elixir Tuple用法及代码示例
- Elixir Time.utc_now用法及代码示例
- Elixir Tuple.sum用法及代码示例
- Elixir Time.to_iso8601用法及代码示例
- Elixir Time.from_iso8601用法及代码示例
- Elixir Time.from_erl!用法及代码示例
- Elixir Time.from_seconds_after_midnight用法及代码示例
- Elixir Tuple.product用法及代码示例
- Elixir Time.truncate用法及代码示例
注:本文由纯净天空筛选整理自elixir-lang.org大神的英文原创作品 Task.async_stream(enumerable, fun, options \\ [])。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。
