Erlang 超时为0的接收 疑问与详解

版权声明:@潘广宇博客, https://blog.csdn.net/panguangyuu/article/details/89150124

一、邮箱的概念

① 每个进程都带有一个邮箱,这个邮箱是和进程同步创建的。

② 给某个进程发送消息后,消息会被放入该进程的邮箱。只有当程序执行第一条接收语句时才会读取邮箱。

二、问题的疑惑

源代码 tester.erl

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

start() ->
    receive
        {alarm, Content} -> io:format("bbb")
    after 0 ->
        receive
            Any -> io:format("xxx")
        end
    end.
c(trec).

Pid = spawn(trec, start, []).

Pid ! {alarm, 123}.

> xxx{alarm, 123}.

当邮箱中出现 {alarm, Content} 时会优先处理对应的表达式并返回,只有当模式匹配都完成后,才能执行 after 0 后面的部分。

那为什么向该进程发送了 {alarm, 123} 却没有打印出 bbb,反而打印出 xxx 并退出了该进程。

原因:spawn() 创建进程的同时,执行了程序代码,一旦程序代码执行,就会立即读取邮箱的消息,而此时,Pid ! {alarm, 123} 的消息还没有发送给该进程,因此邮箱消息为空,直接执行了 after 0 后面的语句,接收到任一一个参数,就输出 xxx 并退出进程。

换个方式看看:

c(trec).

self() ! {alarm, 123}.                 % 向当前shell的进程邮箱发送一条消息

trec:start().                          % 执行代码,读取当前进程的邮箱,能获取到{alarm, 123}消息

> bbbok

分享一段代码分析:

-module(multiproc).
-export([important/0]).

important() ->
    receive
        {Priority, Message} when Priority > 10 ->
            [Message | important()]
    after 0 ->
        normal()
    end.
 
normal() ->
    receive
        {_, Message} ->
            [Message | normal()]
    after 0 ->
        []
    end.
1> c(multiproc).
{ok,multiproc}

2> self() ! {15, high}, self() ! {7, low}, self() ! {1, low}, self() ! {17, high}. 

% 依次向当前shell进程邮箱发送{15, high} {7, low} {1, low} {17, high} 消息
     
{17,high}

3> multiproc:important().

[high,high,low,low]

% 由于第一个消息 {15, high} 条件1,则执行表达式,并将该消息从邮箱内删除。由于第2、3条消息 {7, low} {1, low} 不满足条件1,保留在邮箱的“保存队列”内并从邮箱里删除,第4条满足则执行表达式并从邮箱里删除。然后执行 after 的代码,读取邮箱内剩余的 2、3 条消息,得到最终结果

不错的erlang after分析链接:https://learnyousomeerlang.com/more-on-multiprocessing

猜你喜欢

转载自blog.csdn.net/panguangyuu/article/details/89150124