3

我为一个名为 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,对吧?

4

2 回答 2

6

您很可能将子进程的 start_link 函数(我假设它是一个 gen_server)编写为:

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

这不仅调用了 init/1 函数,而且还使用原子名称注册了进程。

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

为了避免这种名称冲突,您应该使用以下内容:

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

这样没有孩子会有注册名字,你也不会发生冲突。

如果您确实需要注册每个孩子,则可以选择使用gproc

于 2013-04-02T13:36:38.063 回答
5

监管者的子规范标识符将是相同的,simple_one_for_one因为只有一种子类型和许多该类型的子实例(工作者)。

supervisor行为文档

请注意,当重启策略为 时simple_one_for_one,子规范列表必须是只有一个子规范的列表。(忽略子规范标识符。)然后在初始化阶段不启动子进程,但假定所有子进程都使用start_child/2.

于 2013-04-03T12:24:37.973 回答