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

时间:2012-09-03 12:41:17

标签: erlang

在“erlang编程”一书和this堆栈溢出问题中,我看到我们可以使用以下命令为邮箱中的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中可以实现不同的优先级吗?

1 个答案:

答案 0 :(得分:7)

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

  1. 您在“接收高优先级消息”状态下生成接收器
  2. 他没有找到高优先级的消息,因此他进入“接收低优先级消息”状态
  3. 您发送的是高优先级消息,但无法识别
  4. 您发送的优先级较低的消息已被识别
  5. 然后接收器循环并进入“高优先级消息”状态并识别消息
  6. 所以甚至可能会出现死锁,接收器会有大量高优先级消息但无法处理它们导致他陷入低优先级状态

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

    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]).