首页 > 程序人生 > 谈谈定时器(Timer)的使用

谈谈定时器(Timer)的使用

过去的半年,陆陆续续看过不少新同学写的代码,自己也写了不少代码。在这过程中,还是有不少感触的。我们知道,定时器(Timer)在程序中的是非常有用的一种utility。今天这篇文章,就结合自己看代码、写代码过程中的一些经验,来谈谈定时器的使用,包括基本的用法,还有使用过程中的一些误区。

在介绍定时器的使用之前,先简单介绍一下常见的定时器的实现。通常,定时器的是由一个单独的线程+一个最小堆来实现的。单独的线程基本上保证定时事件不被其他事件而阻塞,能够及时调度到,从而保证定时器的在时间上的“准确性”;用最小堆来做为核心的数据结构,主要是为了性能考虑,以时间为key,这样堆顶的元素就是最先到期的,因此每次check的时候,直接从堆顶开始check, 只到遇到第一个没到期的元素为止,这里的复杂度与在堆里的元素个数无关,可以看作是O(1)的,因此性能上还是比较有保障的。

接下来说说定时器的基本用法,通常情况下,定时器有两类主要的应用:一类是周期性的执行某个指定的动作;一类是延后特定的时间,执行指定的动作。第一类我们通常叫周期性定时器(PeriodTimer),第二类叫一次型定时器(OneshotTimer) 。

在具体使用的过程中,一些典型的使用误区,主要包括以下几种:
1. 在定时器里执行非常耗时的事件:这么做最直接的坏处就是,排在当前执行的事件后面的事件,得不到及时的调度执行而被延期,这时候的表现就是定时器“不准时”了。
2. 在定时器里添加大量周期很短事件:这么做最直接的问题是定时器线程本身过于繁忙,影响事件调度的及时性,最终的表现也是“不准时”。

通过上面的介绍,我们知道定时器使用过程中最大的误区就是容易因为误用而导致定时器“不准时”,如何用好定时器,是需要我们考虑的一个问题。这里推荐一种通常情况下都比较靠谱的用法:定时器+线程池的用法。具体做法是,定时器只用作触发定时事件,触发完成以后,将事件的具体执行加入到线程池。这里不区分事件是什么类型的事件(耗时的/阻塞的),都需要加入线程池,定时器本身不执行事件。读者朋友如果在自己的程序中有用到定时器,可以试试上面介绍的方法,这个方法应该能解决绝大部分相关的问题。

分类: 程序人生 标签: ,
  1. hi
    2012年3月25日15:32 | #1

    怎么十多天没有写博客啦, 快点更新博客呀, 每天都到你的博客上看看, 喜欢你写的技术文章

  1. 本文目前尚无任何 trackbacks 和 pingbacks.
您必须在 登录 后才能发布评论.