Elixir 为什么在实现GenServer时,跟踪#引用比跟踪#PID更好?
Elixir’s解释了如何使用Elixir 为什么在实现GenServer时,跟踪#引用比跟踪#PID更好?,elixir,gen-server,Elixir,Gen Server,Elixir’s解释了如何使用GenServer实现包含代理的注册表服务器 每个代理的PID都保存在一个映射中,其中键是客户端提供的代理名称,值是代理的PID 为了避免保留对已死亡代理的引用,该指南建议使用Process.monitor/1监视新创建的代理,并通过添加名为refs的新映射稍微修改状态,其中包含引用(由Process.monitor/1返回的值)作为键,代理的名称作为值。它还显示了如何使用handle_info/2来更新refs来处理监控消息 Process.monitor/1接收
GenServer
实现包含代理的注册表服务器
每个代理的PID都保存在一个映射中,其中键是客户端提供的代理名称,值是代理的PID
为了避免保留对已死亡代理的引用,该指南建议使用Process.monitor/1
监视新创建的代理,并通过添加名为refs
的新映射稍微修改状态,其中包含引用(由Process.monitor/1
返回的值)作为键,代理的名称作为值。它还显示了如何使用handle_info/2
来更新refs
来处理监控消息
Process.monitor/1
接收PID(例如#PID
)作为参数,并返回引用(例如#Reference
)。句柄信息/2
捕获的:DOWN
消息提供PID和参考
因为我们一直都知道这两个值:在
refs
中使用引用作为键比使用PID有什么好处,如果有的话?这是一个一致性问题。虽然您只监视流程,但没有区别。但底层不仅可以监视进程:还有端口等,它们基本上没有PID
从文档:
•对象
触发事件的受监视实体。监视本地进程或端口时,对象
将等于被监视的pid()
或port()
。按名称监视进程或端口时,对象
的格式为{RegisteredName,Node}
,其中RegisteredName
是与监视器/2
调用一起使用的名称,节点
是本地或远程节点名称(对于按名称监视的端口,节点
始终是本地节点名称)
总结:
参考
是一个被监控的实体。它可能是一个进程,一个端口,等等。虽然您不想监视关闭端口的整个进程,但应该使用引用。如果您只是有一个小项目,并且只想监视一些进程,那么只需记住PID即可。但我建议您使用参考资料,因为项目发展很快,您可能希望监控的不仅仅是流程。Elixir在:erlang.monitor/2
下面使用,它还允许您监视端口
以及erlang单调时间和erlang系统时间之间的时间偏移量
。这可以在参考文献中找到,因为参考文献更为通用,一般使用参考文献是一种更好的做法
下面是我想说的一个小例子:
iex(1)> :erlang.monitor(:time_offset, :clock_service)
#Reference<0.0.3.100>
iex(2)> :erlang.monitor(:process ,self())
#Reference<0.0.3.113>
iex(1)>:erlang.monitor(:时间偏移量,:时钟服务)
#参考文献
iex(2)>:erlang.monitor(:进程,self())
#参考文献