【问题标题】:Purpose of `receive after 0` (also known as Selective Receives)`receive after 0` 的目的(也称为选择性接收)
【发布时间】:2014-04-03 15:48:47
【问题描述】:

来自 Learn You Some Erlang for Great Good!

另一种特殊情况是超时为0时:

flush() -> 
  receive
   _ -> flush() 
  after 0 -> 
    ok 
  end
.

当这种情况发生时,Erlang VM 将尝试找到适合的消息 可用的模式之一。在上述情况下,任何东西都匹配。作为 只要有消息,flush/0函数就会递归调用 直到邮箱为空。完成后,after 0 -> ok 部分代码执行完毕,函数返回。

我不明白after 0 的目的。在阅读了上面的文字后,我认为它就像after infinity(永远等待),但我改变了一点刷新功能:

flush2() ->
  receive
    _ -> timer:sleep(1000), io:format("aa~n"), flush()
  after 0 ->
    okss
  end
.

flush3() ->
  receive
    _ -> io:format("aa~n"), flush()
  after 0 ->
    okss
  end
.

在第一个函数中它等待 1 秒,在第二个函数中它不等待。
在这两种情况下,它都不会显示文本 (aa~n)。
所以它不能像after infinity那样工作。

如果receiveafter之间的块没有被执行,那么上面2个代码可以简化为:

flush4() ->
  okss
.

我错过了什么?

ps。我使用的是 Erlang R16B03-1,而我记得这本书的作者使用的是 Erlang R13。

【问题讨论】:

    标签: erlang


    【解决方案1】:

    每个进程都有一个“邮箱”——消息队列。可以通过receive 获取消息。如果队列中没有消息。 after 部分指定 'receive 将等待他们多长时间。所以after 0——意味着进程检查(通过receive)队列中是否有任何消息,如果队列为空,则立即继续下一条指令。

    例如,如果我们想定期检查此处是否有任何消息,并在没有消息时做某事(希望有帮助),则可以使用它。

    【讨论】:

      【解决方案2】:

      你可以玩一下下面的shell命令来了解after命令的效果:

      4> L = fun(G) ->                            
      4> receive                                  
      4> stop -> ok;                               
      4> M -> io:format("received ~p~n",[M]), G(G)
      4> after 0 ->                               
      4> io:format("no message~n")                
      4> end
      4> end.
      #Fun<erl_eval.6.80484245>
      5> F = fun() -> timer:sleep(10000),          
      5> io:format("end of wait for messages, go to receive block~n"),
      5> L(L)end.
      #Fun<erl_eval.20.80484245>
      6> spawn(F).                                 
      <0.46.0>
      end of wait for messages, go to receive block
      no message
      7> P1 = spawn(F).
      <0.52.0>
      8> P1 ! hello.   
      hello
      end of wait for messages, go to receive block
      received hello
      no message
      9> P2 ! hello, P2 ! stop.
      * 1: variable 'P2' is unbound
      8> P2 = spawn(F).        
      <0.56.0>
      9> P2 ! hello, P2 ! stop.
      stop
      end of wait for messages, go to receive block
      received hello
      10> 
      

      【讨论】:

        【解决方案3】:

        after 0 视为finally

        考虑使用after 0 以优先级处理receives:http://learnyousomeerlang.com/more-on-multiprocessing#selective-receives

        愿这种对事物的不同看法能启发你。

        【讨论】:

        • 当被视为 finally 代码分支时,它完全更有意义。
        猜你喜欢
        • 2020-09-11
        • 2012-06-13
        • 2017-11-28
        • 2019-12-25
        • 2015-03-09
        • 2014-03-31
        • 1970-01-01
        相关资源
        最近更新 更多