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/2
true
。 -
: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 \\ [])。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。