【问题标题】:Erlang receive after 0Erlang 在 0 之后接收
【发布时间】:2015-10-21 10:02:53
【问题描述】:

假设我有一个 Erlang 进程,其消息队列目前如下所示:

msg1
msg2
{timeout, Ref1, some_atom}
msg3
msg4

如果我这样做,消息队列会是什么样子:

receive
    {timeout, Ref1, some_atom} ->
        0
after 0
    false
end

【问题讨论】:

    标签: erlang


    【解决方案1】:

    您可以在 shell 中尝试一下以找出答案:

    1> Pid = spawn(fun F() -> receive start -> receive {timeout, Ref1, some_atom} -> F() after 0 -> ok end end end).
    <0.47.0>
    2> Pid ! msg1.
    msg1
    3> Pid ! msg2.
    msg2
    4> Pid ! {timeout, erlang:make_ref(), some_atom}.
    {timeout,#Ref<0.0.8.133>,some_atom}
    5> Pid ! msg3.
    msg3
    6> Pid ! msg4.
    msg4
    7> erlang:process_info(Pid, messages).
    {messages,[msg1,msg2,
               {timeout,#Ref<0.0.8.133>,some_atom},
               msg3,msg4]}
    8> Pid ! start.
    start
    9> erlang:process_info(Pid, messages).
    {messages,[msg1,msg2,msg3,msg4]}
    
    • 命令 1 创建一个进程 Pid 等待接收 start 原子,然后执行您在问题中指定的 receive
    • 命令 2-6 在Pid 中创建与您的问题匹配的消息队列。
    • 命令 7 验证 Pid 消息队列是我们所期望的。
    • 命令 8 发送 start 原子以使 Pid 执行您在问题中指定的 receive,然后返回并等待另一个 start 消息。
    • 命令 9 再次检查Pid 消息队列。正如我们所见,代码收到了{timeout, Ref1, some_atom} 元组,并在队列中留下了msg1 和类似的原子。

    由于 Erlang 的选择性接收能力,命令 9 的结果正是我们所期望的,这导致它在接收消息时会查看消息队列以找到第一个匹配项。如果在这种情况下没有消息匹配,after 0 子句将改为执行,这在此代码中意味着生成的函数将完成,Pid 将退出。

    【讨论】:

    • 你甚至可以发送到 shell (Ref1 = make_ref(), [self() ! M || M &lt;- [msg1, msg2, {timeout, Ref1, some_atom}, msg3, msg4]], receive {timeout, Ref1, some_atom} -&gt; ok after 0 -&gt; ok end, flush().)
    • 是的,after 0 子句保证在立即超时之前搜索消息队列中的匹配消息。
    猜你喜欢
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-09
    • 2012-03-15
    • 2014-02-18
    • 1970-01-01
    相关资源
    最近更新 更多