【转载】gen_server 边缘


我们以 Module 代表 gen_server 的 callback 模块

1, 实现 gen_server behaviour 的模块会产生一个新的 process 么?
毫无疑问,太会了!通过调用 proc_lib:start_link/5 创建 process 。

2, gen_server:start_link/3,4 中的 Options 参数有什么用处? 
Options 中只有这几个选项:{debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts}, 
  • debug 是用来和 sys 模块相关联的;
  • 通过 proc_lib:start_link/5 创建 process 的时候,如果初始化等待的时间超过了 Time ,那么我们的 gen_server:start_link 会返回 {error, timeout} 的错误;
  • spawn_opt 是给 spawn_opt 传递的参数。 

3, Module:init/1 的那些返回值都什么意思? 
{ok, State} 就不用说了,一切正常,State 将为 gen_server 的 State; 
{ok, State, Timeout} 也很正常,只是如果 process 在 Timeout(>=0,ms) 时间内没有收到任何消息,那么将产生一个 timeout 消 息,这个消息要在handle_info 中处理哦。 
{ok, State, hibernate} 还是正常,只是我们在 process 启动后,就让它先”睡眠“,因为我们知道最近一段时间内,我们还不用这个 process,此process 睡眠的好处就是可以最大限度的减少其内存占用,当有消息到达时,process 就会”惊醒“,重新工作。 
{stop, Reason},oops,出错了,process 将会调用 exit(Reason) 退出。如果 init 没有预期,我们就退出吧。 
ingore,既然要求忽略了,什么都不做,退出吧。 

4, gen_server:multi_call/2,3,4 这几个哥们是干嘛用的? 
multi 就是多的意思嘛,mulit_call 肯定就是进行多个调用请求哦。 
先说他们的关系: 
gen_server:multi_call(Name, Request) 
= gen_server:multi_call([node() | nodes()], Name, Request) 
= gen_server:multi_call([node() | nodes()], Name, Request, infinity) 
称他们为兄弟,我看称他们为三胞胎还不错。 
向多个 node 请求本地名为 Name 的 gen_server behaviour ,然后收集结果,返回。 
其返回值格式为:{Replies,BadNodes},其中 Replies 为 [{Node, Reply}] ;BadNodes,不用说就是那些没有正常返回应答的节点了。 
mulit_call/4 最后一个 Time 参数指定的是每个 Reply 等待的超时时间。 

5, gen_server:reply/2 有嘛用处? 
如果在 Module:handle_call/3 中,我们不能返回结果,我们可以保存 handle_call 中的 From 参数,在结果生成的时候,通过 gen_server:reply/2 返回给 Caller 。 

6, Module:handle_call/3 返回 {noreply,NewState} 会怎样? 
怎样?明明 handle_call 处理的是同步的请求,处理完了就应该告诉 Caller,是死是活,是成功是失败,可是你 noreply,  Caller 只能傻傻的等待了。等多久?默认的是 5 秒,gen_server:call/3 就调用 exit({timeout, Description}),退出了。。 

7, 我用 gen_server 竟然死锁了? 
天呀,在 erlang 中怎么遇到锁了?肯定是你使用不当!
name() ->
    gen_server:call(?SERVER, name).
address() ->
    gen_server:call(?SERVER, address).

all_info() ->
    gen_server:call(?SERVER, all_info).

.....
handle_call(all_info, _From, State) ->
    Name = name(),
    Address = address(),
    {reply, {Name, Address}, State};
这么写,活该你死锁。 
handle_call 是同步调用,你在内部又调用 name() 、address() ,能不锁么? 
要求就是:不要在handle_call/3 内部调用另一个 gen_server:call 相关的函数。 


你可能感兴趣的:(erlang,gen_server)