说我有一个文件名列表(.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
并发送多条消息。这样做会同时处理消息吗? Inside Erlang VM文件说每个调度程序有多个运行队列,所以我假设可以同时处理消息?或者为了同时处理消息,我是否必须生成多个进程并向它们发送一条消息?喜欢
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),
是否可以让进程拥有嵌套的接收块?哪种方法更合适?
答案 0 :(得分:3)
Erlang调度程序调度进程而不是消息。如果你想同时发生一些事情,你需要多个过程。
流程内部流程是顺序的,因此archive / 0的实现正在接收消息,然后提取,然后回复,并且在递归后它接收下一条消息。
由于产生一个过程很便宜,每个文件都有一个进程没有错。无需发送消息即可开始处理,您可以在闭包中传递文件名。这里例如列表理解:
[ spawn_link(fun() -> {ok, Fs} = zip:extract(Path, Options), Pid ! {repl, Fs} end) ||
Path <- List ],
%% collect replies
甚至更容易使用rpc:pmap并让它完成所有工作。