- Erlang教程
- Erlang - 主页
- Erlang - 概述
- Erlang - 环境
- Erlang - 基本语法
- Erlang-Shell
- Erlang - 数据类型
- Erlang - 变量
- Erlang - 运算符
- Erlang - 循环
- Erlang - 决策
- Erlang - 函数
- Erlang - 模块
- Erlang - 递归
- Erlang - 数字
- Erlang - 字符串
- Erlang - 列表
- Erlang - 文件 I/O
- Erlang - 原子
- Erlang - 地图
- Erlang - 元组
- Erlang - 记录
- Erlang - 异常
- Erlang - 宏
- Erlang - 头文件
- Erlang - 预处理器
- Erlang - 模式匹配
- Erlang - 守卫
- Erlang-BIFS
- Erlang - 二进制文件
- Erlang - 乐趣
- Erlang - 进程
- Erlang - 电子邮件
- Erlang - 数据库
- Erlang - 端口
- Erlang - 分布式编程
- Erlang-OTP
- Erlang - 并发
- Erlang - 性能
- Erlang - 驱动程序
- Erlang - 网络编程
- Erlang 有用资源
- Erlang - 快速指南
- Erlang - 有用的资源
- Erlang - 讨论
Erlang - 并发
Erlang中的并发编程需要有以下基本原则或流程。
该列表包括以下原则 -
piD = 产卵(有趣)
创建一个新的并发进程来评估 Fun。新进程与调用者并行运行。一个例子如下 -
例子
-module(helloworld). -export([start/0]). start() -> spawn(fun() -> server("Hello") end). server(Message) -> io:fwrite("~p",[Message]).
上述程序的输出是 -
输出
“Hello”
PID!信息
向具有标识符 Pid 的进程发送消息。消息发送是异步的。发送者不会等待,而是继续其正在做的事情。'!' 称为发送运算符。
一个例子如下 -
例子
-module(helloworld). -export([start/0]). start() -> Pid = spawn(fun() -> server("Hello") end), Pid ! {hello}. server(Message) -> io:fwrite("~p",[Message]).
接收…结束
接收已发送到进程的消息。它具有以下语法 -
句法
receive Pattern1 [when Guard1] -> Expressions1; Pattern2 [when Guard2] -> Expressions2; ... End
当消息到达进程时,系统尝试将其与 Pattern1 进行匹配(可能具有保护 Guard1);如果成功,它将计算表达式 1。如果第一个模式不匹配,它将尝试 Pattern2,依此类推。如果没有任何模式匹配,则保存该消息以供以后处理,并且该进程等待下一条消息。
以下程序显示了包含所有 3 个命令的整个过程的示例。
例子
-module(helloworld). -export([loop/0,start/0]). loop() -> receive {rectangle, Width, Ht} -> io:fwrite("Area of rectangle is ~p~n" ,[Width * Ht]), loop(); {circle, R} -> io:fwrite("Area of circle is ~p~n" , [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(helloworld). -export([max/1,start/0]). max(N) -> Max = erlang:system_info(process_limit), io:format("Maximum allowed processes:~p~n" ,[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) microseconds~n" , [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).
在任何具有良好处理能力的机器上,上述两个 max 函数都会通过。以下是上述程序的示例输出。
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(helloworld). -export([sleep/1,start/0]). sleep(T) -> receive after T -> true end. start()-> sleep(1000).
上面的代码在实际退出之前会Hibernate 1000 Ms。
选择性接收
Erlang 中的每个进程都有一个关联的邮箱。当您向进程发送消息时,该消息将被放入邮箱中。检查此邮箱的唯一时间是当您的程序评估接收语句时。
以下是选择性接收语句的一般语法。
句法
receive Pattern1 [when Guard1] -> Expressions1; Pattern2 [when Guard1] -> Expressions1; ... after Time -> ExpressionTimeout end
这就是上面的接收语句的工作原理 -
当我们输入接收语句时,我们启动一个计时器(但前提是表达式中存在 after 部分)。
获取邮箱中的第一条消息并尝试将其与 Pattern1、Pattern2 等进行匹配。如果匹配成功,则将从邮箱中删除该邮件,并计算该模式后面的表达式。
如果接收语句中没有任何模式与邮箱中的第一条消息匹配,则第一条消息将从邮箱中删除并放入“保存队列”中。然后尝试邮箱中的第二条消息。重复此过程,直到找到匹配的邮件或直到检查完邮箱中的所有邮件为止。
如果邮箱中没有消息匹配,则该进程将被挂起,并将在下次将新消息放入邮箱时重新安排执行。注意,当有新消息到达时,保存队列中的消息不会重新匹配;仅匹配新消息。
一旦消息匹配,所有已放入保存队列的消息都会按照到达进程的顺序重新输入邮箱。如果设置了计时器,则将其清除。
如果在等待消息时计时器已过,则计算表达式 ExpressionsTimeout 并按照消息到达进程的顺序将所有保存的消息放回到邮箱中。