无涯教程-Erlang - 并发

85 阅读4分钟

创建一个新的并发过程以执行Fun,新进程与调用方并行运行。如下-

-module(helloLearnfk). 
-export([start/0]). 

start() -> spawn(fun() -> server("Hello") end).

server(Message) -> io:fwrite("~p",[Message]).

上面程序的输出是-

Hello

发送消息(Pid ! Message)

向标识符为Pid的进程发送消息,消息发送是异步的,发送者不等待,而是继续其所做的事情。!被称为发送运算符。

-module(helloLearnfk). 
-export([start/0]). 
start() -> 
   Pid=spawn(fun() -> server("Hello") end), 
   Pid ! {hello}. 

server(Message) -> io:fwrite("~p",[Message]).

接收消息(Receive...end)

接收已发送到进程的消息。它具有以下语法-

receive
Pattern1 [when Guard1] ->
Expressions1;
Pattern2 [when Guard2] ->
Expressions2;
...
End

当消息到达进程时,系统会尝试将其与Pattern1匹配(可能有Guard 1),如果成功,它将判断Expressions1。如果第一个模式不匹配,则尝试使用Pattern2,依此类推。如果没有任何一个模式匹配,则保存该消息以供以后处理,然后该过程等待下一条消息。

以下程序显示了使用所有3条命令的整个过程的示例。

-module(helloLearnfk). 
-export([loop/0,start/0]). 

loop() -> receive {rectangle, Width, Ht} -> io:fwrite("Area of rectangle is pn" ,[Width Ht]), loop(); {circle, R} -> io:fwrite("Area of circle is pn" , [3.14159 R * R]), loop(); Other -> io:fwrite("Unknown"), loop() end.

start() -> Pid=spawn(fun() -> loop() end), Pid ! {rectangle, 6, 10}.

关于上述程序,需要注意以下几点:

  • 循环功能具有接收结束循环,因此,发送消息时,它将由接收端循环处理。

  • 产生了一个新的过程,该过程进入了循环功能。

  • 消息通过Pid发送到生成的进程!消息命令。

上面程序的输出是-

Area of the Rectangle is 60

最大进程数

同时进行,重要的是确定系统上允许的最大进程数,然后,您应该能够了解系统上可以同时执行多少个进程。

让我们看一个示例,该如何确定系统上可以执行的最大进程数。

-module(helloLearnfk). 
-export([max/1,start/0]). 

max(N) -> Max=erlang:system_info(process_limit), io:format("Maximum allowed processes:pn" ,[Max]),

statistics(runtime), statistics(wall_clock),

L=for(1, N, fun() -> spawn(fun() -> wait() end) end), {, Time1}=statistics(runtime), {, Time2}=statistics(wall_clock), lists:foreach(fun(Pid) -> Pid ! die end, L),

U1=Time1 1000/N, U2=Time2 1000/N, io:format("Process spawn time=~p (p) microsecondsn" , [U1, U2]). wait() ->

receive die -> void end.

for(N, N, F) -> [F()]; for(I, N, F) -> [F()|for(I+1, N, F)].

start()-> max(1000), max(100000).

在任何具有良好处理能力的机器上,上述两个最大功能都会通过。

Maximum allowed processes:262144
Process spawn time=47.0 (16.0) microseconds
Maximum allowed processes:262144
Process spawn time=12.81 (10.15) microseconds

超时设置

有时,receive语句可能会永远等待永远不会出现的消息,这可能是出于多种原因。如,我们的程序中可能存在逻辑错误,或者要向我们发送消息的进程在发送消息之前可能已崩溃,为避免此问题,我们可以将超时添加到接收语句,这设置了进程等待接收消息的最长时间。

以下是指定了超时的接收消息的语法

receive 
Pattern1 [when Guard1] -> 
Expressions1; 

Pattern2 [when Guard2] -> Expressions2; ... after Time -> Expressions end

最简单程序示例所示。

-module(helloLearnfk). 
-export([sleep/1,start/0]). 

sleep(T) -> receive after T -> true end.

start()-> sleep(1000).

上面的代码在实际退出之前将休眠1000Ms。

选择性接收

Erlang中的每个进程都有一个关联的信箱,当您向该进程发送消息时,该消息将放入箱中,仅当程序判断接收语句时,才检查此箱。

以下是选择性接收语句的一般语法。

receive 
Pattern1 [when Guard1] ->
Expressions1; 

Pattern2 [when Guard1] -> Expressions1; ... after Time -> ExpressionTimeout end

这就是上面的接收语句的工作方式-

  • 当我们输入一个接收语句时,我们将启动一个计时器。

  • 接收信箱中的第一条消息,然后尝试将其与Pattern1,Pattern2等匹配,如果匹配成功,则会从箱中删除该邮件,并执行匹配的表达式。

  • 如果接收语句中的任何模式都不匹配箱中的第一条消息,则将从箱中删除第一条消息并将其放入"save queue"。然后尝试箱中的第二条消息。重复此过程,直到找到匹配的消息或检查了箱中的所有消息为止。

  • 如果箱中的所有件都不匹配,则该过程将被挂起,并将在下次将新件放入信箱中时重新安排执行时间。

  • 一旦匹配了一条消息,所有放入保存队列中的消息就会按照到达过程的顺序重新输入到箱中。如果设置了计时器,则将其清除。

  • 如果在等待消息时计时器已过,ExpressionsTimeout并将所有保存的消息按到达过程的顺序放回箱。

参考链接

www.learnfk.com/erlang/erla…