2014-04-19 2 views
1

파일 이름 목록 (.zip)이 있습니다. 나는 파일을 동시에 (병렬) 추출하고 추출 된 각 파일에 대해 병렬로 처리하려고한다. 나의 현재 코드는 일부 무엇처럼 :여러 가지 프로세스를 재미있게 만들거나 생성하고 여러 메시지를 보내야합니까?

start() -> 
    % .. 
    Pid = spawn_link(fun process/0), 
    Pid ! {self(), process_stats}, 
    receive 
     {Pid, Response} -> Response; 
     {'EXIT', Pid, Reason} -> .. 
    end. 

process() -> 
    receive 
     {Pid, process_stats} -> 
      Apps = get_apps(), 
      Archive = spawn_link(fun archive/0), 
      lists:foreach(fun({Id, AppId}) -> 
           Archive ! {self(), {extract, ?STATS_DIR++AppId++".zip", Pid}} 
          end, Apps), 
      process(); 
     {Pid, {onextract, FilesList, Reply}} -> 
      Reply ! {self(), ok}, % 
      process();    
    end. 

archive() -> 
    receive 
     {Pid, {extract, FilePath, Reply}} -> % Passing in Reply so that the receive block can send back message to the initiator. But it looks odd. 
      {ok, FilesList} = zip:extract(FilePath, [{cwd, ?STATS_DIR}]), 
      Pid ! {self(), {onextract, FilesList, Reply}}, 
      archive() 
    end. 

get_apps() -> ok. % returns a list of file names. 

그래서, 내 질문은 내가 하나의 프로세스 만 Archive을 spawing 여러 메시지를 보내고있다이다. 그렇게하면 메시지가 동시에 처리됩니까? Inside Erlang VM 신문에 따르면 각 스케줄러에 대해 여러 개의 실행 대기열이 있으므로 메시지를 동시에 처리 할 수 ​​있다고 가정합니다. 또는 메시지를 동시에 처리하려면 여러 프로세스를 생성하여 각각 하나의 메시지를 보내야합니까? like

 lists:foreach(fun({Id, AppId}) -> 
          Archive = spawn_link(fun archive/0), 
          Archive ! {self(), {extract, ?STATS_DIR++AppId++".zip"}}, % Here I don't have to send the Reply Pid as the receive statement is within. 
          receive 
           {Archive, {onextract, FilesList}} -> ok. % Is it ok to have nested receive blocks within a process? 
          end 
         end, Apps), 

중첩 수신 블록을 갖는 것이 좋습니까? 어떤 접근 방식이 더 적합합니까?

답변

3

얼랭 스케쥴러는 메시지가 아닌 프로세스를 스케줄링합니다. 동시에 어떤 일이 일어나길 원한다면 여러 프로세스가 필요합니다.

프로세스 내의 플로우는 순차적이므로, archive/0 구현은 메시지를 수신 한 다음 압축을 풀고 응답 한 다음 다시 회귀 한 후 다음 메시지를 수신합니다.

프로세스를 생성하는 것이 저렴하기 때문에 파일 당 처리하는 데는 문제가 없습니다. 처리를 시작하기 위해 메시지를 보낼 필요가 없습니다. 파일 이름을 닫을 때 전달할 수 있습니다. 예 :

[ spawn_link(fun() -> {ok, Fs} = zip:extract(Path, Options), Pid ! {repl, Fs} end) || 
     Path <- List ], 
%% collect replies 

또는 더 쉽게 사용 rpc:pmap하고 모든 일을하자 : 지능형리스트와 함께.

관련 문제