再谈关键字 receive
官方解释:
Receives messages sent to the process using the send operator (!). The patterns Pattern are sequentially matched against the first message in time order in the mailbox, then the second, and so on. If a match succeeds and the optional guard sequence GuardSeq is true, the corresponding Body is evaluated. The matching message is consumed, that is, removed from the mailbox, while any other messages in the mailbox remain unchanged.
The return value of Body is the return value of the receive expression.
receive never fails. The execution is suspended, possibly indefinitely, until a message arrives that matches one of the patterns and with a true guard sequence.
我之前的理解的用法是:
step1: spawn 一个 process PID
step2: 使用receive语法来接受外界给我的message
P = erlang:spawn(fun() -> ... end ).
receive
MSG -> io:format("receive a message ~p",[MSG])
end.
我才开始接受消息
当时今天我做了一个实验,我觉得不应该这么理解,receive不是我接受消息,而应该理解是我去消息队列去取第一条消息,如果没有我想取的消息,将会堵塞下去,进程的消息队列是创建之后就存在的,我只要不去取,不去消费,消息队列会越来越长
1> F = fun()-> receive MSG -> io:format("receive msg ~p",[MSG]) end end.
#Fun<erl_eval.20.99386804>
2> P = erlang:spawn(F).
<0.71.0>
3> erlang:monitor(process,P).
#Ref<0.2577153742.3274702852.114500>
4> P ! msg.
receive msg msgmsg
5> erlang:process_info(self(),messages).
{messages,[{'DOWN',#Ref<0.2577153742.3274702852.114500>,
process,<0.71.0>,normal}]}
// 这个这条消息就存在我的消息队列中(mail box)
// 这个时候就可以使用receive 语法去取出这条消息,进行处理,如果没有匹配不上,就会堵塞
6>receive {a} -> io:format("a",[]) after 5000 -> timeout end.
timeout
// 如果消息没有被取出来,那么还会存在消息队列中
7> erlang:process_info(self(),messages).
{messages,[{'DOWN',#Ref<0.2577153742.3274702852.114500>,
process,<0.71.0>,normal}]}
// 使用 receive 取出第一条消息(msg)
8> receive X -> io:format("msg:~p",[X]) after 5000 -> timeout end.
msg:{'DOWN',#Ref<0.2577153742.3274702852.114500>,process,<0.71.0>,normal}ok
// 消息一旦被取出,那么就会从消息队列移除
9> erlang:process_info(self(),messages).
{messages,[]}
总结
receive 其实是取出消息的含义取出信箱中匹配的信息
网友评论