我正在编写一个程序,使用Erlang多处理解决生产者 - 消费者问题,其中一个流程负责处理我生产/消费的缓冲区以及许多生产者和许多消费者流程。为了简化,我假设生产者/消费者不知道他的操作已经失败(由于缓冲区约束而无法生成或使用),但服务器已准备好这样做。
我的代码是:
服务器代码
server(Buffer, Capacity, CountPid) ->
receive
%% PRODUCER
{Pid, produce, InputList} ->
NumberProduce = lists:flatlength(InputList),
case canProduce(Buffer, NumberProduce, Capacity) of
true ->
NewBuffer = append(InputList, Buffer),
CountPid ! lists:flatlength(InputList),
Pid ! ok,
server(NewBuffer,Capacity, CountPid);
false ->
Pid ! tryagain,
server(Buffer, Capacity, CountPid)
end;
%% CONSUMER
{Pid, consume, Number} ->
case canConsume(Buffer, Number) of
true ->
Data = lists:sublist(Buffer, Number),
NewBuffer = lists:subtract(Buffer, Data),
Pid ! {ok, Data},
server(NewBuffer, Capacity,CountPid);
false ->
Pid ! tryagain,
server(Buffer, Capacity, CountPid)
end
end.
制作人和消费者
producer(ServerPid) ->
X = rand:uniform(9),
ToProduce = [rand:uniform(500) || _ <- lists:seq(1, X)],
ServerPid ! {self(),produce,ToProduce},
producer(ServerPid).
consumer(ServerPid) ->
X = rand:uniform(9),
ServerPid ! {self(),consume,X},
consumer(ServerPid).
启动和辅助功能(我附上,因为我不知道我的问题究竟在哪里)
spawnProducers(Number, ServerPid) ->
case Number of
0 -> io:format("Spawned producers");
N ->
spawn(zad2,producer,[ServerPid]),
spawnProducers(N - 1,ServerPid)
end.
spawnConsumers(Number, ServerPid) ->
case Number of
0 -> io:format("Spawned producers");
N ->
spawn(zad2,consumer,[ServerPid]),
spawnProducers(N - 1,ServerPid)
end.
start(ProdsNumber, ConsNumber) ->
CountPid = spawn(zad2, count, [0,0]),
ServerPid = spawn(zad2,server,[[],20, CountPid]),
spawnProducers(ProdsNumber, ServerPid),
spawnConsumers(ConsNumber, ServerPid).
canProduce(Buffer, Number, Capacity) ->
lists:flatlength(Buffer) + Number =< Capacity.
canConsume(Buffer, Number) ->
lists:flatlength(Buffer) >= Number.
append([H|T], Tail) ->
[H|append(T, Tail)];
append([], Tail) ->
Tail.
我正在尝试使用这样的进程计算元素数量,服务器会在生成元素时向其发送消息。
count(N, ThousandsCounter) ->
receive
X ->
if
N >= 1000 ->
io:format("Yeah! We have produced ~p elements!~n", [ThousandsCounter]),
count(0, ThousandsCounter + 1000);
true -> count(N + X, ThousandsCounter)
end
end.
我希望这个程序能够正常工作,这意味着:它产生元素,生成元素的增加取决于时间,如f(t)= kt,k-constant和我生产的生产速度越快的过程。
实际问题
我启动了程序:
erl
c(zad2)
zad2:start(5,5)
程序的行为:
为什么我的程序行为不像我期望的那样?我在使用Erlang编程时遇到了什么问题,还是操作系统或其他任何问题?
答案 0 :(得分:0)
上面写的producer / 1和consumer / 1函数不会等待任何事情 - 它们只是循环和循环,用消息轰炸服务器。服务器的消息队列正在快速填满,Erlang VM将尽可能地增长,窃取所有内存,循环进程将窃取所有内核的所有可用CPU时间。