【发布时间】:2011-10-14 23:18:12
【问题描述】:
消息是按先到先得的方式处理的,还是按时间戳或类似的方式排序的?
【问题讨论】:
标签: erlang
消息是按先到先得的方式处理的,还是按时间戳或类似的方式排序的?
【问题讨论】:
标签: erlang
为了进一步定义答案,我想指出一个事实,如上所述,不匹配的消息会被跳过,但实际上它们只是被放在一边,然后按顺序重新引入(所以首先任何其他消息在不匹配消息之后到达)用于下一次接收模式匹配。
当你有一个 gen_server 行为模块时,这个问题确实表现得最糟糕,因为在这种情况下,总是有相同的模式匹配调用方案,除非你定义一个(丑陋并且容易出错,恕我直言)匹配所有模式,例如:
receive
... -> ...;
... -> ...;
MatchAllPatterns -> ok.
end
【讨论】:
消息的顺序在一个进程和另一个进程之间保留。读自FAQ:
10.9 消息接收顺序是否有保证?
是的,但仅限于一个进程内。
如果有一个实时进程并且您向它发送消息 A 然后发送消息 B,保证如果消息B到达,消息A之前到达 它。
另一方面,想象进程 P、Q 和 R。P 将消息 A 发送到 Q,然后向 R 发送消息 B。不能保证 A 到达 在 B 之前。(如果这样,分布式 Erlang 将会非常艰难 是必需的!)
@knutin 关于如何在进程中使用消息是正确的。另外,请注意,您可能会使用 两个 后续接收语句来确保在 另一个消息之后使用某个消息:
receive
first ->
do_first()
end,
receive
second ->
do_second()
end
接收语句被阻塞。这将确保您在do_first() 之前永远不会do_second()。与@knutin 的第二个解决方案的不同之处在于,在这种情况下,如果不 重要的东西刚好在重要 的东西之前到达,你就将重要的部分排队。
【讨论】:
邮箱始终按照邮件到达的顺序保存。
但是,消息的消费顺序由您的代码决定。
如果您有一个普通的流程,其中包含接收任何内容的通用 receive 子句,那么您收到消息的顺序与它们到达的顺序相同。
loop() ->
receive
Any ->
do_something(Any),
loop()
end.
但是,如果您有一个带有匹配子句的选择性receive,它将在邮箱中搜索此特定类型的消息并使用第一条匹配的消息,从而有效地跳过不匹配的消息。在以下示例中,如果队列中有标记为重要的消息,它们将在任何其他消息之前被处理。注意:像这样匹配会搜索队列中的所有消息,这是很多消息的问题。这方面有一些发展,但我跟不上。
loop() ->
receive
{important, Stuff} ->
do_something_important(Stuff),
loop();
Any ->
do_something(Any)
loop()
end.
【讨论】:
foreach message { foreach pattern { if it matches ...} }。在最后一个代码 sn-p 中,如果邮箱中存在与{important, ...} 不匹配的较早消息,它将在任何重要的事情之前收到。另请参阅stackoverflow.com/questions/12248111/…