erl_0011 erlang 定时器相关

转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=20764167&id=4470124

3.1  The timer module

Creating timers using erlang:send_after/3 and erlang:start_timer/3 is much more efficient than 
using the timers provided by the timer module. The timer module uses a separate process to manage 
the timers, and that process can easily become overloaded if many processes create and cancel timers 
frequently (especially when using the SMP emulator).

The functions in the timer module that do not manage timers (such as timer:tc/3 or timer:sleep/1), 
do not call the timer-server process and are therefore harmless.

refer: http://www.erlang.org/doc/efficiency_guide/commoncaveats.html#id60818

-----------------------------------------------------------------------------------------------------------------
那么 send_after 和 start_timer 又有什么区别呢,
直接看文档,发现没有什么区别
但是文档一比较,发现一个核心的问题,就在于它们在超时的时候发送的东西不同。


send_after 发送的是个 Msg 消息体,
start_timer 发送的则是 {timeout, TimerRef, Msg} 包含了定时器引用的tuple,
这样接收者就可以区分具体是哪个定时器超时了。

refer: http://www.iteye.com/topic/634815

这2个API都返回 TimerRef. 用户可以用这个TimerRef来取消定时器. 唯一的差别是在超时的时候发送的消息不同: send_after是Msg, start_timer是{timeout, TimerRef, Msg}. 
问题就出在取消timer的时候. 如果这个timer还没有超时的时候, 那么取消就没问题. 
如果超时了麻烦就来了, 这个消息已经有可能已经被放到目标进程的消息队列里,等待派遣处理了. 

这时候send_after里面存放的是Msg, 那用户如何知道Msg是对于那个TimerRef的呢? 读者可能说, 那我可以在消息里面加入TimerRef. 这个主意不错,
但是问题是在send_after调用返回之前, 你是无法得到TimerRef, 当然也就无从构造这个消息, 那就无法处理这个可能的超时信息, 就会破坏逻辑. 
所以erts version 5.4.11 引入了, start_timer来解决这个问题.
 它是自动的在超时后, 要发送消息前, 在消息里面添加了{timeout, TimerRef, Msg}, 达到识别的目的
原文地址:https://www.cnblogs.com/rsblog/p/4344493.html