Elixir - 受监督的进程似乎会阻止程序执行
Elixir - Supervised processes appear to block program execution
写了一些小实验来熟悉这门语言,但是运行进入了一个我猜是初级的问题。
我有一个简单的主管,有 3 个简单的工人:
def init do
Supervisor.start_link(
[
worker(__MODULE__, [:"process-1"], [function: :test, id: :"p-1"]),
worker(__MODULE__, [:"process-2"], [function: :test, id: :"p-2"]),
worker(__MODULE__, [:"process-3"], [function: :test, id: :"p-3"])
],
strategy: :one_for_one
)
end
“:测试”看起来像这样:
def test(name) do
flag(:trap_exit, true)
IO.puts "Testing: #{name} == #{inspect self}"
register(self, name)
receive do
{ :death } ->
IO.puts("I WOZ MURDERED!")
exit(self, "Ex process...")
{ :life } ->
IO.puts("#{inspect self} is listening...")
__MODULE__.test(name)
{ :EXIT, pid, reason } ->
IO.puts "REASON: #{inspect reason} - PROCESS: #{inspect pid}"
end
end
这可以编译,但它只会产生一个进程,并且 hangs/blocks iex.
相比之下,当我使用一个简单的“spawn_link”进程链时,所有三个(或许多)进程同时启动并且 return 控制 iex shell 这样我就可以从命令行发送注册进程消息了。
目前,我的意图是创建一个 OTP 主管,运行 并注册三个(或多个)工作进程并将它们附加到主管,发送一条简单的消息来杀死给定的工作人员,然后让主管重新启动它。
我做错了什么?
问题是 function:
你作为工人规范的一部分提供的不符合 OTP 的期望。
来自http://www.erlang.org/doc/man/supervisor.html
The start function must create and link to the child process, and
should return {ok,Child} or {ok,Child,Info} where Child is the pid of
the child process and Info an arbitrary term which is ignored by the
supervisor.
您的代码不会产生子代,但会进入接收循环。你也许可以使用 Elixir 的 Task
模块来做一些类似于你想要的事情:
worker(Task, [__MODULE__, :test, [:"process-1"]], id: :"p-1"),
worker(Task, [__MODULE__, :test, [:"process-2"]], id: :"p-2"),
worker(Task, [__MODULE__, :test, [:"process-3"]], id: :"p-3")
但是,如果您想了解更多关于 OTP 的功能,那么尝试实施您自己的 GenServer
可能是更好的选择。
写了一些小实验来熟悉这门语言,但是运行进入了一个我猜是初级的问题。
我有一个简单的主管,有 3 个简单的工人:
def init do
Supervisor.start_link(
[
worker(__MODULE__, [:"process-1"], [function: :test, id: :"p-1"]),
worker(__MODULE__, [:"process-2"], [function: :test, id: :"p-2"]),
worker(__MODULE__, [:"process-3"], [function: :test, id: :"p-3"])
],
strategy: :one_for_one
)
end
“:测试”看起来像这样:
def test(name) do
flag(:trap_exit, true)
IO.puts "Testing: #{name} == #{inspect self}"
register(self, name)
receive do
{ :death } ->
IO.puts("I WOZ MURDERED!")
exit(self, "Ex process...")
{ :life } ->
IO.puts("#{inspect self} is listening...")
__MODULE__.test(name)
{ :EXIT, pid, reason } ->
IO.puts "REASON: #{inspect reason} - PROCESS: #{inspect pid}"
end
end
这可以编译,但它只会产生一个进程,并且 hangs/blocks iex.
相比之下,当我使用一个简单的“spawn_link”进程链时,所有三个(或许多)进程同时启动并且 return 控制 iex shell 这样我就可以从命令行发送注册进程消息了。
目前,我的意图是创建一个 OTP 主管,运行 并注册三个(或多个)工作进程并将它们附加到主管,发送一条简单的消息来杀死给定的工作人员,然后让主管重新启动它。
我做错了什么?
问题是 function:
你作为工人规范的一部分提供的不符合 OTP 的期望。
来自http://www.erlang.org/doc/man/supervisor.html
The start function must create and link to the child process, and should return {ok,Child} or {ok,Child,Info} where Child is the pid of the child process and Info an arbitrary term which is ignored by the supervisor.
您的代码不会产生子代,但会进入接收循环。你也许可以使用 Elixir 的 Task
模块来做一些类似于你想要的事情:
worker(Task, [__MODULE__, :test, [:"process-1"]], id: :"p-1"),
worker(Task, [__MODULE__, :test, [:"process-2"]], id: :"p-2"),
worker(Task, [__MODULE__, :test, [:"process-3"]], id: :"p-3")
但是,如果您想了解更多关于 OTP 的功能,那么尝试实施您自己的 GenServer
可能是更好的选择。