这是任何 erlang 进程的因果报应:它等待或死亡 :o)
当一个进程被生成时,它开始执行直到最后一个执行行,然后死掉,返回最后一个评估。
为了使进程保持活动状态,没有其他解决方案可以在无休止的连续调用中递归循环。
当然有几个条件让它停止或休眠:
- 循环结束:进程收到一条消息,告诉他
停止递归
- 接收块:进程将等待直到收到消息
匹配接收块中的一个条目将发布在消息中
排队。
- VM 调度程序暂时停止它以允许访问 CPU
到其他进程
在最后两种情况下,执行将在 VM 调度程序的责任下重新启动。
在等待时它不使用 CPU 带宽,但保持与开始等待时完全相同的内存布局。 Erlang OTP 提供了一些方法来使用 hibernate 选项将这种内存布局减少到最低限度(请参阅 gen_serevr 或 gen_fsm 的文档,但在我看来它仅供高级使用)。
创建将定期(或几乎定期)间隔触发进程的“信号”的一种简单方法是有效地使用带有 timout 的接收块(超时限制为 65535 毫秒),例如:
on_tick_sec(Module,Function,Arglist,Period) ->
on_tick(Module,Function,Arglist,1000,Period,0).
on_tick_mn(Module,Function,Arglist,Period) ->
on_tick(Module,Function,Arglist,60000,Period,0).
on_tick_hr(Module,Function,Arglist,Period) ->
on_tick(Module,Function,Arglist,60000,Period*60,0).
on_tick(Module,Function,Arglist,TimeBase,Period,Period) ->
apply(Module,Function,Arglist),
on_tick(Module,Function,Arglist,TimeBase,Period,0);
on_tick(Module,Function,Arglist,TimeBase,Period,CountTimeBase) ->
receive
stop -> stopped
after TimeBase ->
on_tick(Module,Function,Arglist,TimeBase,Period,CountTimeBase+1)
end.
及用法:
1> Pid = spawn(util,on_tick_sec,[io,format,["hello~n"],5]).
<0.40.0>
hello
hello
hello
hello
2> Pid ! stop.
stop
3>
[编辑]
timer 模块是一个标准的 gen_server,在一个单独的进程中运行。 timer 模块中的所有函数都是公共接口,它们执行隐藏的 gen_server:call 或 gen_server:cast 到 timer 服务器。这是隐藏服务器内部并允许进一步演进而不影响现有应用程序的常见用法。
服务器在内部使用一个表(ets)来存储它必须执行的所有操作以及每个计时器引用,并且它使用自己的函数在需要时唤醒(最后,VM 必须处理这个? )。
因此,您可以使进程休眠,而不会影响计时器服务器的行为。休眠机制是
- 棘手,请参阅hibernate/3 definition 的文档,您将看到您必须自己“重建”上下文,因为所有内容都已从进程上下文中删除,并且系统存储了一个元组(Module,Function,Arguments}在需要时重新启动您的流程。
- 在垃圾收集和进程重启方面花费了一些时间
这就是为什么我说它确实是一个需要充分理由使用的高级功能。