我正在学习 Elixir 任务模块。 https://hexdocs.pm/elixir/1.12/Task.html
在
Task.start()
内使用 Task.asyn_stream()
安全吗?
这会导致进程泄漏吗?
这会导致进程泄漏吗?
你可以这样写:
defmodule A do
def go do
Task.async_stream(
[500, 100],
fn x ->
{:ok, pid } = Task.start(fn -> Process.sleep(:infinity) end)
IO.inspect pid
Process.sleep(x)
end
)
end
end
在 iex 中:
~/elixir_programs% iex a.ex
Erlang/OTP 24 [erts-12.3.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1]
Interactive Elixir (1.14.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(3)> stream = A.go
#Function<3.111522547/2 in Task.build_stream/3>
iex(4)> Stream.run(stream)
#PID<0.121.0>
#PID<0.123.0>
:ok
iex(5)> IEx.configure(inspect: [limit: :infinity])
:ok
iex(5)> Process.list
[#PID<0.0.0>, #PID<0.1.0>, #PID<0.2.0>, #PID<0.3.0>, #PID<0.4.0>, #PID<0.5.0>,
#PID<0.6.0>, #PID<0.7.0>, #PID<0.10.0>, #PID<0.42.0>, #PID<0.44.0>,
#PID<0.46.0>, #PID<0.47.0>, #PID<0.49.0>, #PID<0.50.0>, #PID<0.51.0>,
#PID<0.52.0>, #PID<0.53.0>, #PID<0.54.0>, #PID<0.55.0>, #PID<0.56.0>,
#PID<0.57.0>, #PID<0.58.0>, #PID<0.59.0>, #PID<0.60.0>, #PID<0.61.0>,
#PID<0.62.0>, #PID<0.63.0>, #PID<0.64.0>, #PID<0.65.0>, #PID<0.66.0>,
#PID<0.67.0>, #PID<0.68.0>, #PID<0.69.0>, #PID<0.70.0>, #PID<0.71.0>,
#PID<0.78.0>, #PID<0.79.0>, #PID<0.80.0>, #PID<0.82.0>, #PID<0.85.0>,
#PID<0.86.0>, #PID<0.87.0>, #PID<0.88.0>, #PID<0.89.0>, #PID<0.91.0>,
#PID<0.92.0>, #PID<0.93.0>, #PID<0.94.0>, #PID<0.95.0>, #PID<0.96.0>,
#PID<0.99.0>, #PID<0.100.0>, #PID<0.101.0>, #PID<0.102.0>, #PID<0.103.0>,
#PID<0.104.0>, #PID<0.105.0>, #PID<0.114.0>, #PID<0.121.0>, #PID<0.123.0>]
您可以看到,即使
Task.start
返回后,0.121.0
进程0.123.0
和Stream.run(stream)
仍在运行,这意味着Task.async_stream
启动的所有进程都已完成。
任何代码都可能导致进程泄漏:如果您创建了一个进程并且丢失了该进程的 pid,那么您将无法控制该进程,除非您关闭该进程正在运行的节点或波束实例。
Task.start()
返回 pid;如果你丢失了 pid,那么如果进程永远运行,你就会遇到进程泄漏。
在 elxir/erlang 中,进程非常轻量级,不需要太多资源,因此您可以启动数百万个进程,而不会导致系统超载。因此,如果有一千个进程发生泄漏,也没什么大不了的。当然,您不希望在相对较长的时间内不断泄漏数千个进程,因为这可能会导致您的系统崩溃。