5

在“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}.

但结果是:

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

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

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.

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

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

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

4

1 回答 1

9

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

  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]).
于 2012-09-03T14:33:12.963 回答