Chinaunix首页 | 论坛 | 博客
  • 博客访问: 537528
  • 博文数量: 80
  • 博客积分: 1496
  • 博客等级: 上尉
  • 技术积分: 1292
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-18 11:24
个人简介

IT码农一个~

文章分类

全部博文(80)

文章存档

2020年(3)

2019年(7)

2017年(1)

2016年(2)

2015年(2)

2014年(26)

2013年(26)

2012年(2)

2011年(1)

2010年(1)

2008年(9)

我的朋友

分类: Erlang

2014-09-13 16:25:26

erlang提供了好几种地方,可以创建一个定时器,但是使用起来却有很多不同的地方。

第一次写代码,直接在gen_server里面使用了 timer的apply_after , 导致timer_server占用cpu很高,
后来看了 文档发现:

3.1  The timer module

Creating timers using  and  is much more efficient than
using the timers provided by the  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: 

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


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

refer: 

这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}, 达到识别的目的



阅读(3747) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~