2012-12-04 2 views

답변

4

좋아는 "감독자"이었다. 자, 학습의 목적을 위해, 아주 기본적인 예를 들어 보겠습니다. 다른 사람들은 OTP Supervisors, Process dictionaries e.t.c에 대해 이야기 할 것입니다. 그러나 나는 그것을 배우기 쉬운 목적으로 유지하고 싶다. 예를 들어, 발전기는 자신이 생성 한 프로세스의 수 (예 : Pids)가 e.t.c.

 
-module(generator). 
-compile(export_all). 
-define(ERROR(X),error_logger:error_report(X)).
start()-> register(generator,spawn(fun() -> generator() end)), ok.
generator()-> ProcessBuffer = [], process_flag(trap_exit,true), loop(ProcessBuffer).
create(Module,Function,Args)-> generator ! {create_new_proc,{Module,Function,Args}}, ok.
send_to_kids(Message)-> generator ! {tell_kids,Message}, ok.
loop(Buffer)-> receive {create_new_proc,{M,F,A}} -> Pid = spawn(M,F,A), link(Pid), loop([Pid|Buffer]); {tell_kids,Message} -> [ Kid ! {broadcast,Message} || Kid <- Buffer], loop(Buffer); {'EXIT',SomePid,Reason} -> ?ERROR(["Child has crashed",{pid,SomePid},{reason,Reason}]), loop(lists:delete(SomePid,Buffer)); _ -> loop(Buffer) end.
child_loop()-> receive {broadcast,Message} -> io:format("\n\tChild: ~p got: ~p~n",[self(),Message]), child_loop(); _ -> child_loop() end.
쉘에서 테스트
 
E:\Applications>erl 
Eshell V5.9 (abort with ^G) 
1> c(generator). 
{ok,generator} 
2> generator:start(). 
ok 
3> generator:create(generator,child_loop,[]). 
ok 
4> [generator:create(generator,child_loop,[]) || _ <- lists:seq(1,5)],ok. 
ok 
5> generator:send_to_kids("Erlang is good !"). 
     Child: <0.45.0> got: "Erlang is good !" 
     Child: <0.44.0> got: "Erlang is good !" 
     Child: <0.43.0> got: "Erlang is good !" 
     Child: <0.42.0> got: "Erlang is good !" 
     Child: <0.41.0> got: "Erlang is good !" 
     Child: <0.39.0> got: "Erlang is good !" 
ok 
6> generator:send_to_kids("1+1 = 2"). 
     Child: <0.45.0> got: "1+1 = 2" 
     Child: <0.44.0> got: "1+1 = 2" 
     Child: <0.43.0> got: "1+1 = 2" 
     Child: <0.42.0> got: "1+1 = 2" 
     Child: <0.41.0> got: "1+1 = 2" 
     Child: <0.39.0> got: "1+1 = 2" 
ok 
7> 
generator으로 등록 된 프로세스가 시작되고 임의의 수의 하위 프로세스를 시작하라는 메시지가 표시 될 수 있습니다. 자식 프로세스는 일반적으로 {M, F, A} 조합으로 생성되어 generator으로 전송됩니다. 생성자 루프는 생성 된 프로세스의 트랙 레코드를 유지합니다. 그런 다음 모든 프로세스에 메시지를 브로드 캐스트하라는 메시지를받을 수 있습니다.

그러나 실제/생산에서는 generator 루프가 Buffer 목록이 증가함에 따라 많은 메모리를 소비 할 수 있기 때문에이 과정을 Pids까지 유지하므로이 작업을 수행하지 않을 수도 있습니다. ETS Tables 또는 Mnesia e.t.c를 사용할 수도 있지만 좀 더 고급화되어 보이므로 예제에서는 사용하지 않습니다. 더 많은 것을 이해하려면이 question과 그 answer을보십시오.

+0

고마워요! 프로세스가 새로운 프로세스를 생성하지만 정확히 어디에 있습니까? 그리고 생성 된 프로세스를 추적하기 위해 변수를 사용할 수 없었습니까? – user1301428

+0

'generator : create/3' 함수를 사용하면 제공된'{M, F, A}'를 실행할 새로운 프로세스를 생성하도록'generator' 프로세스에게 요청합니다. '{create_new_proc, {M, F, A}}'메시지를 받았을 때 생성기'loop/1'을 따르고 셸에서'create/3' 함수를 어떻게 사용하는지 확인하십시오 –

+1

내 눈이 맞다면 .. 충돌시 예상대로 작동하지 않습니다. 'trap_exit' 프로세스 플래그가 없으므로''EXIT''는 결코 도착하지 않을 것입니다. 또한 때때로 충돌이 발생하면 프로세스의 오류 상태를 추적하기 위해'spawn_link' 또는 아마도'spawn_monitor'를 사용하려고합니다. 보다 완벽한 예는 프로세스를 simple_one_for_one 수퍼바이저 트리에 생성 된 상태로 유지하는 것입니다. –

관련 문제