2013-04-02 51 views
1

我定義simple_one_for_one工人規格爲一名監事名爲band_supervisor,孩子規範ID爲jam_musician爲什麼simple_one_for_one工作人員可以共享同一個Child Spec ID?

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,對嗎?

+0

你可以發佈你的音樂家模塊代碼嗎?看起來您正在註冊具有相同名稱的子進程。 – Isac

+0

是的,您的代碼也適用於主管模塊。有些事情是錯誤的,因爲你無法從'simple_one_for_one'管理器獲得'already_started'。 – rvirding

+0

@Isac已更新,子規格ID可以重複? – why

回答

2

由於只有一個子類型和許多這種類型的子實例(worker),所以子規範ID將與sofo supervisors相同。

docs

注意,當重新啓動策略是simple_one_for_one,孩子規格列表必須是隻有一個孩子規格列表。 (Id被忽略)。然後在初始化階段沒有啓動子進程,但所有子進程都假定使用supervisor start_child/2動態啓動。

4

最有可能你寫的子進程(我認爲這是一個gen_server)由於START_LINK功能:

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

這不僅調用init/1功能,而且還使用原子名稱註冊過程。

因此,任何在第二時刻開始的新孩子都會嘗試使用第一個孩子已經使用的名字在erlang節點內註冊。

爲了避免這種命名衝突,你應該使用類似:

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

所以沒有兒童將有一個註冊名,你不會有任何衝突。

如果你真的需要註冊每個孩子,一個選項可能包括使用gproc

+2

這將產生一個錯誤,而不是'already_started'返回。如果您使用** not **'simple_one_for_one'超級用戶執行'restart_child/2',並且您嘗試啓動已啓動的ID,則您只**獲得'already_started'。你不能通過一個'simple_one_for_one'超級用戶管理器來取得id,這個超級用戶名將被忽略。 – rvirding

+0

感謝您的澄清+1 – user601836

+0

對不起,我認爲你是對的,我已經更新了我的問題! – why

相關問題