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 \\ [])。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。