这就是任何 erlang 进程的业力:它等待或死亡:o)
当一个进程产生时,它开始执行直到最后一个执行行,然后死亡,返回最后一个评估。
为了使进程保持活动状态,没有其他解决方案可以在永无休止的连续调用中递归循环。
当然有几个条件让它停止或者休眠:
- 循环结束:进程收到一条消息,告诉他
停止递归
- 接收块:进程将等待消息
与接收块中的一项匹配的条目将发布在消息中
队列。
- VM调度程序暂时停止它以允许访问CPU
到其他进程
在最后两种情况下,执行将在 VM 调度程序的负责下重新启动。
等待时,它不使用 CPU 带宽,但会保持与开始等待时完全相同的内存布局。 Erlang OTP 提供了一些方法,使用 hibernate 选项将内存布局减少到最小(请参阅 gen_serevr 或 gen_fsm 的文档,但在我看来,它仅用于高级用途)。
创建一个以规则(或几乎规则)间隔触发进程的“信号”的简单方法是有效地使用带有超时的接收块(超时限制为 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>
[edit]
计时器模块是一个在单独进程中运行的标准 gen_server。定时器模块中的所有函数都是公共接口,它们执行隐藏的 gen_server:call 或 gen_server:cast 到定时器服务器。这是隐藏服务器内部并允许进一步发展而不影响现有应用程序的常见用法。
服务器在内部使用一个表(ets)来存储它必须执行的所有操作以及每个计时器引用,并且它使用自己的函数在需要时被唤醒(最后,VM 必须处理这个?)。
因此,您可以休眠进程,而不会对计时器服务器行为产生任何影响。休眠机制是
- 棘手,请参阅文档hibernate/3 定义 http://www.erlang.org/doc/man/erlang.html#hibernate-3,您将看到您必须自己“重建”上下文,因为所有内容都已从流程上下文中删除,并且系统存储了一个元组(模块,函数,参数}以在需要时重新启动您的流程。
- 花费一些时间进行垃圾收集和进程重启
这就是为什么我说它确实是一个高级功能,需要充分的理由才能使用。