首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Erlang:主管(3),添加子进程

Erlang:主管(3),添加子进程
EN

Stack Overflow用户
提问于 2011-01-29 13:48:48
回答 2查看 8.1K关注 0票数 14

如何将动态子进程添加到现有监管器(simple_one_for_one重新启动策略的示例)?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-01-29 16:03:28

我做了一些研究,下面是我所拥有的。

首先,这是主管的一个示例回调模块:

代码语言:javascript
复制
-module(root_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).

start_link() ->
     {ok, Pid} = supervisor:start_link({local, ?MODULE}, 
          ?MODULE, []),
     {ok, Pid}.

init(_Args) ->
     RestartStrategy = {simple_one_for_one, 10, 60},
     ChildSpec = {ch1, {ch1, start_link, []},
          permanent, brutal_kill, worker, [ch1]},
     Children = [ChildSpec],
     {ok, {RestartStrategy, Children}}.

这是一个子模块的回调模块,它将动态地添加到子树中:

代码语言:javascript
复制
-module(ch1).

-behaviour(gen_server).

% Callback functions which should be exported
-export([init/1]).
-export([handle_cast/2]).

% user-defined interface functions
-export([start_link/0]).

start_link() ->
     gen_server:start_link(?MODULE, [], []).

init(_Args) ->
     io:format("ch1 has started (~w)~n", [self()]),
     % If the initialization is successful, the function
     % should return {ok,State}, {ok,State,Timeout} ..
     {ok, ch1State}.

handle_cast(calc, State) ->
     io:format("result 2+2=4~n"),
     {noreply, State};
handle_cast(calcbad, State) ->
     io:format("result 1/0~n"),
     1 / 0,
     {noreply, State}.

我们通常是这样开始上司的:

代码语言:javascript
复制
1> ch_sup:start_link().
{ok,<0.33.0>}

现在让我们开始我们的第一个子进程:

代码语言:javascript
复制
2> {ok, Child1Pid} = supervisor:start_child(ch_sup, []).
ch1 has started (<0.35.0>)
{ok,<0.35.0>}

您可以动态启动子进程;让我们启动另一个子进程:

代码语言:javascript
复制
3> {ok, Child2Pid} = supervisor:start_child(ch_sup, []).
ch1 has started (<0.37.0>)
{ok,<0.37.0>}

您可能会看到,我们的过程确实开始了(注意最后两个):

代码语言:javascript
复制
4> erlang:processes().
[<0.0.0>,<0.2.0>,<0.4.0>,<0.5.0>,<0.7.0>,<0.8.0>,<0.9.0>,
 <0.10.0>,<0.11.0>,<0.12.0>,<0.13.0>,<0.14.0>,<0.15.0>,
 <0.16.0>,<0.17.0>,<0.18.0>,<0.19.0>,<0.20.0>,<0.21.0>,
 <0.22.0>,<0.23.0>,<0.24.0>,<0.25.0>,<0.26.0>,<0.27.0>,
 <0.31.0>,<0.33.0>,<0.35.0>,<0.37.0>]

现在让我们的第一个子进程做一些事情:

代码语言:javascript
复制
5> gen_server:cast(Child1Pid, calc).
result 2+2=4
ok

到现在为止还好。现在,我们将让我们的第一个孩子评估一些错误的代码:

代码语言:javascript
复制
6> gen_server:cast(Child1Pid, calcbad).
result 1/0
ok    
7> 
=ERROR REPORT==== 10-Feb-2011::01:32:15 ===
** Generic server <0.35.0> terminating 
** Last message in was {'$gen_cast',calcbad}
** When Server state == ch1State
** Reason for termination == 
** {'function not exported',
       [{ch1,terminate,
            [{badarith,
                 [{ch1,handle_cast,2},
                  {gen_server,handle_msg,5},
                  {proc_lib,init_p_do_apply,3}]},
             ch1State]},
        {gen_server,terminate,6},
        {proc_lib,init_p_do_apply,3}]}
ch1 has started (<0.42.0>)
7>

在报告中,您可能会看到零的除法导致异常,并且进程被终止。但是主管会处理它,并立即启动另一个子进程(注意最后一行)。

我们可以检查以确保我们以前启动的另一个子进程仍然处于活动状态(注意<0.37.0>):

代码语言:javascript
复制
7> erlang:processes().                 
[<0.0.0>,<0.2.0>,<0.4.0>,<0.5.0>,<0.7.0>,<0.8.0>,<0.9.0>,
 <0.10.0>,<0.11.0>,<0.12.0>,<0.13.0>,<0.14.0>,<0.15.0>,
 <0.16.0>,<0.17.0>,<0.18.0>,<0.19.0>,<0.20.0>,<0.21.0>,
 <0.22.0>,<0.23.0>,<0.24.0>,<0.25.0>,<0.26.0>,<0.27.0>,
 <0.31.0>,<0.33.0>,<0.37.0>,<0.42.0>]
8>

我们甚至可以让它为我们做些什么:

代码语言:javascript
复制
8> gen_server:cast(Child2Pid, calc).   
result 2+2=4
9>

下面是您想要阅读的Erlang手册页:

  • 主管行为
  • 主管(3)
  • 服务器(3)
票数 20
EN

Stack Overflow用户

发布于 2011-01-29 15:10:30

在Erlang的主管行为部分的OTP设计原则部分中,有一个如何使用simple_one_for_one和动态子文档的示例。我推荐整个设计原则部分,因为它提供了许多关于OTP如何工作的洞察力。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4837196

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档