【问题标题】:How to give different priorities to erlang messages如何为erlang消息赋予不同的优先级
【发布时间】:2012-08-28 04:56:14
【问题描述】:

在“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 中实现不同的优先级吗?

【问题讨论】:

    标签: erlang


    【解决方案1】:

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

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

    【讨论】:

    • 顺便问一下,我可以在 handle_info 中实现优先级吗?
    • @user601836 我不太确定,抱歉
    • @user601836 您的意思是在 gen_server 或 gen_fsm 中?不,你不能,无论如何都不容易喜欢这里。消息接收是在 gen_server 循环中为您完成的,因此 handle_infohandle_callhandle_cast 按消息到达的顺序被调用。您可以像上面那样显式检查handle_info 中的高优先级消息,但在发生其他事情之前不会发生。这是使用 gen_servers 的缺点之一,您会失去对接收消息的明确控制。
    • 感谢您指出这一点,然后我会坚持我自己的自定义流程,使用 proc_lib:start_link 启动它
    猜你喜欢
    • 2018-09-12
    • 1970-01-01
    • 2015-02-11
    • 2018-11-20
    • 2012-05-31
    • 1970-01-01
    • 2012-02-06
    • 2023-02-13
    • 1970-01-01
    相关资源
    最近更新 更多