为什么simple_one_for_one工作人员可以共享相同的Child Spec Id?

时间:2013-04-02 10:21:36

标签: erlang otp

我为一个名为band_supervisor的主管定义了simple_one_for_one工作规范,子规范ID为jam_musician

  init([]) ->
    {ok, {{simple_one_for_one, 3, 60},
    [{jam_musician,
    {musicians, start_link, []},
    temporary, 1000, worker, [musicians]}
    ]}};

音乐家模块是:

-module(musicians).
-behaviour(gen_server).

-export([start_link/2, stop/1]).
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, code_change/3, terminate/2]).

-record(state, {name="", role, skill=good}).
-define(DELAY, 750).

start_link(Role, Skill) ->
  gen_server:start_link({local, Role}, ?MODULE, [Role, Skill], []).

stop(Role) -> gen_server:call(Role, stop).

我可以通过以下方式创建许多工作人员:

3> supervisor:start_child(band_supervisor, [drum, good]).
Musician Arnold Ramon, playing the drum entered the room
{ok,<0.696.0>}
3> supervisor:start_child(band_supervisor, [guitar, good]).
Musician Wanda Perlstein, playing the guitar entered the room
{ok,<0.698.0>}

我注意到所有工作人员都有相同的儿童规范ID:jam_musician

您知道其他类型的工作人员必须具有唯一的子ID,对吗?

2 个答案:

答案 0 :(得分:5)

最有可能你写了子进程的start_link函数(我假设它是gen_server):

start_link() ->
    gen_server:start_link({local,Name}, ?MODULE, [], []).

这不仅调用init / 1函数,还使用atom Name注册进程。

因此,在第二个时刻开始的任何新孩子将尝试使用第一个孩子已经采用的名称在erlang节点内注册。

为了避免这种名称冲突,你应该使用类似的东西:

start_link() ->
    gen_server:start_link(?MODULE, [], []).

所以没有孩子会有一个注册名称,你就不会发生冲突。

如果您确实需要注册每个孩子,则选项可能包括使用gproc

答案 1 :(得分:2)

对于sofo主管,子规范ID将是相同的,因为只有一种子类型和许多此类型的子实例(工作者)。

来自docs

  

请注意,当重启策略为simple_one_for_one时,子规范列表必须是仅包含一个子规范的列表。 (Id被忽略)。在初始化阶段,不会启动子进程,但假定所有子进程都是使用supervisor动态启动的:start_child / 2.