如何给不同的优先级给erlang消息 [英] How to give different priorities to erlang messages

查看:165
本文介绍了如何给不同的优先级给erlang消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在erlang程序设计一书中,以及这个堆栈溢出问题我已经看到,我们可以给邮箱中的erlang消息提供不同的优先级:



我试图实现类似于此代码的东西:

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

start() - >
注册(?MODULE,spawn(fun() - > do_receive()end))。

do_receive() - >
接收
{high_p,Message} - >
io:format(High priority:〜p〜n,[Message]),
do_receive()
after 0 - >
收到
{low_p,Message} - >
io:format(低优先级:〜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的:测试()。
低优先级:msg2
{high_p,msg3}
高优先级:msg1
高优先级:msg3

哪个看起来不对,所以我更改了代码:

  do_receive ) - > 
接收
{high_p,Message} - >
io:format(High priority:〜p〜n,[Message]),
do_receive()
after 0 - >
接收
{high_p,_} =其他 - >
self()!其他,
do_receive();
{low_p,Message} - >
io:format(低优先级:〜p〜n,[Message]),
do_receive()
end
end。

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

  1> mytest的:start()方法。 
true
2> mytest的:测试()。
高优先级:msg3
{high_p,msg3}
高优先级:msg1
低优先级:msg2

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

解决方案

第一个程序会发生什么:


  1. 您在接收高优先级消息状态下生成接收者

  2. 他发现没有高优先级消息你会发送一个高优先级的消息,但没有被识别

  3. 你发送一个低优先级的消息,它被认可

  4. 然后接收器循环并进入高优先级消息状态并识别消息

所以甚至可能是一个僵局,接收者将有一大堆高优先级的消息,但不能处理它们,因为他被困在低优先级状态



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

  do_receive() - > 
接收
{high_p,Message} - >
do_high(Message)
after 0 - >
接收
{high_p,Message} - >
do_high(Message);
{low_p,Message} - >
io:format(低优先级:〜p〜n,[Message])
end
end,
do_receive()。

do_high(Message) - >
io:format(高优先级:〜p〜n,[消息])。


In the book "erlang programming" and in this stack overflow question I have seen that we can give different priorities to erlang messages in the mailbox using:

I tried to implement something similar with this code:

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

But the result was:

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

Which seems not right, so I changed the code as:

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.

and the result is the following (all high priority messages are printed before the low priority ones).

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

Is this the correct way in order to achieve my goal? And can different priorities be achieved within gen_server handle_info/2 ?

解决方案

what happens in the first program is:

  1. you spawn the receiver at the "receive high-priority message" state
  2. he finds no high-priority message so he goes to "receive low-priority message" state
  3. you send a high priority message but it's not recognised
  4. you send a low priority message and it is recognised
  5. then the receiver loops and goes to the "high priority message" state and recognises the messages

so there could even be a deadlock where the receiver would have a ton of high-priority messages but cannot process them cause he's stuck in the low-priority state

therefore, I think that your approach (which is similar to the answer to the question you linked) is better. an optimisation: since you receive a high-priority message there is no need to send it again (and cause additional overhead):

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

这篇关于如何给不同的优先级给erlang消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆