zoukankan      html  css  js  c++  java
  • 用Erlang求解建环问题

     代码如下所示

      1 -module(ring).
      2 -behaviour(gen_server).
      3 -export([start/3, ring_item_init/1]).
      4 
      5 %% 行为模式gen_server的回调函数
      6 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
      7 
      8 -define(SERVER, ?MODULE).
      9 
     10 %% 环中各个节点进程的状态,id:标识,从1开始,next:下一个进程号
     11 -record(state, {id, next}).
     12 
     13 %% 监督进程的状态,process_counter:环中节点的数量
     14 -record(server_state, {process_counter}).
     15 
     16 %% 入口函数,M:循环发送消息的次数,N:环中节点的数量,Message:循环的消息内容
     17 start(M, N, Message) ->
     18     gen_server:start_link({local, ?SERVER}, ?MODULE, #server_state{process_counter=N}, []),
     19     create_ring(N),             % 创建环
     20     transmit_msg(Message, M),   % 在环中循环传递消息
     21     destroy_ring().             % 删除环
     22 
     23 create_ring(N) ->
     24     gen_server:call(?SERVER, {create_ring, N}).
     25 
     26 transmit_msg(Message, M) ->
     27     gen_server:call(?SERVER, {transmit_msg, Message, M}).
     28 
     29 destroy_ring() ->
     30     gen_server:call(?SERVER, destroy_ring).
     31 
     32 init(State) ->
     33     process_flag(trap_exit, true),
     34     {ok, State}.
     35 
     36 handle_call(Request, From, State) ->
     37     case Request of
     38         {create_ring, N} ->
     39             create_ring_impl(1, undefined, N);
     40         {transmit_msg, Message, M} ->
     41             transmit_msg_impl(Message, M * State#server_state.process_counter);
     42         destroy_ring ->
     43             header ! {quit, State#server_state.process_counter};
     44         _ -> ok
     45     end,
     46     {reply, From, State}.
     47 
     48 %% 创建环的算法实现 Id:新节点进程的标识,Pre:上一个进程的Pid,
     49 %% Max:环中节点的数量
     50 
     51 %% 创建头节点
     52 create_ring_impl(1, undefined, Max) ->
     53     Pid = spawn_link(?MODULE, ring_item_init, [#state{id=1}]),
     54     register(header, Pid),
     55     create_ring_impl(2, Pid, Max);
     56 %% 创建尾节点
     57 create_ring_impl(Id, Pre, Id) ->
     58     Pid = spawn_link(?MODULE, ring_item_init, [#state{id=Id}]),
     59     Pre ! {next, Pid},
     60     Pid ! {next, header};
     61 %% 创建中间节点
     62 create_ring_impl(Id, Pre, Max) ->
     63     Pid = spawn_link(?MODULE, ring_item_init, [#state{id=Id}]),
     64     Pre ! {next, Pid},
     65     create_ring_impl(Id+1, Pid, Max).
     66 
     67 transmit_msg_impl(Message, MsgTransmitCounter) ->
     68     header ! {msg, Message, MsgTransmitCounter},
     69     receive
     70         complete -> io:format("circle complete~n");
     71         _ -> ok
     72     end.
     73 
     74 %% 节点进程的初始化函数    
     75 ring_item_init(#state{id=Id}=State) ->
     76     io:format("process ~p is created~n", [Id]),
     77     loop(State),
     78     ok.
     79 
     80 %% 节点进程的循环处理函数
     81 loop(#state{id=Id}=State) ->
     82     receive
     83         {next, Next} ->        % 设置当前节点进程链接的下一节点 
     84             io:format("process ~p pid=~p , next is ~p~n", [Id, self(), Next]),
     85             loop(State#state{next=Next});
     86         {msg, Message, MsgTransmitCounter} ->     % 向下一节点传递消息
     87             io:format("process ~p receive ~p, MsgTransmitCounter:~p~n", [Id, Message, MsgTransmitCounter]),
     88             case MsgTransmitCounter-1 =:= 0 of
     89                 true -> 
     90                     ?SERVER ! complete,
     91                     loop(State);
     92                 false ->
     93                     State#state.next ! {msg, Message, MsgTransmitCounter-1},
     94                     loop(State)
     95             end;
     96         {quit, MsgTransmitCounter} ->        % 当前节点进程退出并向下一节点发送退出消息
     97             io:format("~p exit~n", [State#state.id]),
     98             case MsgTransmitCounter-1 =:= 0 of
     99                 true -> exit(normal);
    100                 false ->
    101                     State#state.next ! {quit, MsgTransmitCounter-1},
    102                     exit(normal)
    103             end
    104     end.
    105     
    106 handle_cast(Request, State) ->
    107     {noreply, State}.
    108 
    109 handle_info(Info, State) ->
    110     {noreply, State}.
    111 
    112 terminate(Reason, State) ->
    113     ok.
    114 
    115 code_change(OldVsn, State, Extra) ->
    116     {ok, State}.

    编程注意事项:进程名可注册为原子,其它进程可向该原子发送信息,但如果进程退出,向原子发送信息会弹出bagarg的exit错误

    上善若水
  • 相关阅读:
    Java对象的生命周期与作用域的讨论(转)
    [置顶] Oracle学习路线与方法
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
  • 原文地址:https://www.cnblogs.com/netbuddy/p/2817762.html
Copyright © 2011-2022 走看看