为什么在实现GenServer时跟踪#Reference比#PID更好?

时间:2016-09-21 03:32:19

标签: elixir gen-server

Elixir的Mix and OTP Guide Chapter GenServer解释了如何使用GenServer实现代理服务器控制代理。

每个代理的PID都保存在一个映射中,其中键是客户端给出的代理名称,值是代理的PID。

为了避免保留对死代理的引用,本指南建议使用Process.monitor/1监视新创建的代理,并通过添加一个名为refs的新映射稍微修改状态,该映射包含引用(返回的值) Process.monitor/1)作为键和代理的名称作为值。它还说明了如何使用handle_info/2更新refs处理监控消息。

Process.monitor/1接收PID(例如#PID<0.66.0>)作为参数并返回参考(例如#Reference<0.0.0.551>)。 :DOWN捕获的handle_info/2消息提供PID和参考。

因为我们始终都知道这两个值:使用引用作为使用refs中的PID的关键有什么好处,如果有的话?

2 个答案:

答案 0 :(得分:3)

这是一致性的问题。虽然您只监控过程,但没有区别。但是基础:erlang.monitor/2可以监控不仅进程:有端口等,基本上没有PID

来自doc:

  

Object

     

被监控的实体,它触发了该事件。监控本地流程或端口时,Object将等于受监控的pid()port()。在按名称监控流程或端口时,Object的格式为{RegisteredName, Node},其中RegisteredNamemonitor/2电话使用的名称,Node是本地或远程节点名称(对于按名称监视的端口,Node始终是本地节点名称)。

总结:Reference是一个被监控的实体。它可能是一个过程,一个端口,等等。虽然您不希望demonitor/1关闭监控端口的整个过程,但您应该使用引用。

答案 1 :(得分:2)

如果您只有一个小项目并且想要监控某些进程,那么只记住PID就可以了。但我建议使用Reference,因为Projects增长很快,您可能不仅要监视进程。 Elixir在:erlang.monitor/2下方使用,它还允许您在Erlang单调时间和Erlang系统时间之间监视portstime_offset。这可以在Docs here中找到。参考是更通用的,并且是更常用的参考。

这是我想说的一个小例子:

iex(1)> :erlang.monitor(:time_offset, :clock_service)
#Reference<0.0.3.100>

iex(2)> :erlang.monitor(:process ,self())
#Reference<0.0.3.113>