如何为erlang消息提供不同的优先级

use*_*836 3 erlang

在"erlang编程"一书中,在这个堆栈溢出问题中,我看到我们可以使用以下命令为邮箱中的erlang消息提供不同的优先级:

我尝试用这段代码实现类似的东西:

-module(mytest).
-export([start/0, test/0]).

start() ->
    register(?MODULE, spawn(fun() -> do_receive() end)).

do_receive() ->
    receive
        {high_p, Message} ->
            io:format("High priority: ~p~n", [Message]),
            do_receive()
    after 0 ->
            receive
                {low_p, Message} ->
                    io:format("Low priority: ~p~n", [Message]),
                    do_receive()
            end
    end.

test() ->
    mytest ! {high_p, msg1},
    mytest ! {low_p, msg2},
    mytest ! {high_p, msg3}.
Run Code Online (Sandbox Code Playgroud)

但结果是:

1> mytest:start().
true
2> mytest:test(). 
Low priority: msg2
{high_p,msg3}
High priority: msg1
High priority: msg3
Run Code Online (Sandbox Code Playgroud)

这似乎不对,所以我将代码更改为:

do_receive() ->
    receive
        {high_p, Message} ->
            io:format("High priority: ~p~n", [Message]),
            do_receive()
    after 0 ->
            receive
                {high_p, _} = Other ->
                    self() ! Other,
                    do_receive();
                {low_p, Message} ->
                    io:format("Low priority: ~p~n", [Message]),
                    do_receive()
            end
    end.
Run Code Online (Sandbox Code Playgroud)

结果如下(所有高优先级消息都在低优先级消息之前打印).

1> mytest:start().
true
2> mytest:test(). 
High priority: msg3
{high_p,msg3}
High priority: msg1
Low priority: msg2
Run Code Online (Sandbox Code Playgroud)

这是实现目标的正确方法吗?在gen_server handle_info/2中可以实现不同的优先级吗?

Tha*_*dis 7

第一个程序中发生的事情是:

  1. 您在"接收高优先级消息"状态下生成接收器
  2. 他找不到高优先级的消息,因此他进入"接收低优先级消息"状态
  3. 您发送高优先级的消息,但它无法识别
  4. 您发送一个低优先级的消息,它被识别
  5. 然后接收器循环并进入"高优先级消息"状态并识别消息

所以甚至可能会出现死锁,接收器会有大量高优先级消息,但无法处理它们导致他陷入低优先级状态

因此,我认为你的方法(与你所关联的问题的答案类似)更好.优化:由于您收到高优先级消息,因此无需再次发送(并导致额外开销):

do_receive() ->
    receive
        {high_p, Message} ->
            do_high(Message)
    after 0 ->
            receive
                {high_p, Message} ->
                    do_high(Message);
                {low_p, Message} ->
                    io:format("Low priority: ~p~n", [Message])
            end
    end,
    do_receive().

do_high(Message) ->
    io:format("High priority: ~p~n", [Message]).
Run Code Online (Sandbox Code Playgroud)