接收块如何工作?

时间:2016-02-05 13:57:59

标签: erlang

我刚才有一个简单的问题,我似乎无法找到答案。基本上我的问题是,如果我有一个功能记录状态(递归)并且我向它发送多个消息,它是否会继续通过接收块,直到它的"邮箱中不再有消息"?

MimeMessage mimeMessage = email.toMimeMessage(userId, context);
Message message = createMessageWithEmail(mimeMessage);
Gmail.Users.Messages messages = service.users().messages();
Gmail.Users.Messages.Send send = messages.send(userId, message);
send.execute(); // method hangs when using large attachment

因此,如果我使用"!"向此过程发送3条消息(Pat1,Pat2,Pat1)。并且它在接收消息之前无法进入其循环,它是否仍会打印出以下内容?

state(Fridge) ->
    receive
        Pat1 ->
            io:format("ok"),
            state(S);
        Pat2 ->
            io:format("not ok"),
            state(S)
    end.

很抱歉,如果不清楚这一点,通过简化问题可能会让我难以想象我的问题。

3 个答案:

答案 0 :(得分:6)

您的问题并不清楚,但您似乎在询问该流程是否会收到这三条消息,即使这些消息是在目标流程调用receive之前发送的 - 如果是这样的话 - '问题是,答案是肯定的。当您向进程发送消息时,它会进入该进程的消息队列,直到进程调用receive将其从消息队列中删除并处理它。

如果您致电erlang:process_info(Pid, messages)Pid是接收方的进程ID,您可以看到其队列中有哪些消息。您可以从Erlang shell中尝试这个。

作为消息排队的一个极端示例,在某些重负载条件下,如果接收方无法跟上快速发送方,它可能成为内存不足问题的根源。在这些条件下,接收者的消息队列可能会无限制地增长,直到系统内存不足为止。

答案 1 :(得分:2)

这会回答你的问题吗?

1> OUT = fun(X) -> io:format(">>> ~p~n", [X]) end.
#Fun<erl_eval.6.54118792>
2> F = fun X() -> receive foo -> OUT(foo), X(); bar -> OUT(bar), X() end end.
#Fun<erl_eval.44.54118792>
3> P = spawn(F).
<0.38.0>
4> [ P ! X || X <- [foo, bar, foo]].
>>> foo
[foo,bar,foo]
>>> bar
>>> foo

邮件到达邮箱,然后receive模式应用于邮件,如函数子句或case语句。但与那些不同的是,如果它们都不匹配,则处理下一条消息,并在消息框中保留前一条消息。其他receive子句始终从消息队列的开头开始。

1> OUT = fun(X) -> io:format(">>> ~p~n", [X]) end.
#Fun<erl_eval.6.54118792>
2> F = fun() -> receive start -> (fun X() -> receive foo -> OUT(foo), X(); bar -> OUT(bar), X() end end)() end end.
#Fun<erl_eval.20.54118792>
3> P = spawn(F).
<0.38.0>
4> [ P ! X || X <- [foo, bar, foo]].
[foo,bar,foo]
5> P! start.
>>> foo
start
>>> bar
>>> foo

请注意,foo, bar, foo位于第一个receive的队列中,但未处理。当start到达时(队列中的最后一个),第二个receive会开始处理foobar个消息。

答案 2 :(得分:0)

-module(wy).
-compile(export_all).

state() ->
    timer:sleep(2000),
    io:format("~p~n", [erlang:process_info(self(), messages)]),
    receive
        pat1 ->
            io:format("ok~n"),
            state();
        pat2 ->
            io:format("not ok~n"),
            state()
    end.
main() ->
    Pid = spawn(fun state/0),
    [ Pid ! X || X <- [pat1, pat2, pat1]].

您可以从输出中运行此代码,您可以理解所有内容。

**注意:**当您向进程发送邮件时,已发送的邮件将存储在该进程的邮箱中。

6> wy:main().
[pat1,pat2,pat1]
7> {messages,[pat1,pat2,pat1]}
7> ok
7> {messages,[pat2,pat1]}
7> not ok
7> {messages,[pat1]}
7> ok
7> {messages,[]}
7>

您的代码有一条评论:

receive
    Pat1 ->
        io:format("ok"),
        state(S);
    Pat2 ->
        io:format("not ok"),
        state(S)
end.

第二个条款不会永远匹配。