python单线程实现多个定时器示例


Posted in Python onMarch 30, 2014

单线程实现多个定时器

NewTimer.py

#!/usr/bin/env python
from heapq import *
from threading import Timer
import threading
import uuid
import time
import datetime
import sys
import math
global TimerStamp
global TimerTimes
class CancelFail(Exception):
    pass
class Slot(object):
    def __init__(self, period=0, interval=1, function=None, args=[], kwargs={}):
        self.period = period
        self.pc = 0
        self.interval = interval
        self.fire = 0
        self.id = uuid.uuid1()
        self.function = function
        self.args = args
        self.kwargs = kwargs
#system resolution millisecond         
class NewTimer(object):
    #set enough time make thread sleep, when NewTimer empty set enoug time, too
    #make sure sum of your timer call back function execute time shorter than resolution
    #todo use a worker thread to operate timer call back function
    def __init__(self, resolution=1000):
        global TimerStamp
        TimerStamp = int(time.time() * 1000)
        self.nofire = sys.maxint #next fire time interval
        self.firestamp = self.nofire + TimerStamp
        self.resolution = resolution# 1s
        self.lock = threading.RLock()
        self.wait = dict()
        self.ready = dict()
        self._start()
    """ private operate ready list """
    def _addToReadyList(self, slot, firestamp):
        box = dict( [ (slot.id, slot)])
        if not self.ready.has_key( firestamp ):
            self.ready.update( [(firestamp, box)] )
        else:
            boxs = self.ready.get(firestamp)
            boxs.update( box )
    def _delFromReadyList(self, slot):
        boxs = self.ready.get(slot.fire)
        try:
            box = boxs.pop(slot.id)
            if not boxs:
                self.ready.pop(slot.fire)
        except (AttributeError, KeyError):
            raise CancelFail
    """ inside """
    def _start(self):
        global TimerStamp
        try:
            self.firestamp = sorted( self.ready.keys() )[0]
            stamp = float((TimerStamp + self.firestamp - int(time.time()*1000)))/1000
        except IndexError:
            self.firestamp = self.nofire
            stamp = self.nofire
        try:
            self.timer.cancel()
        except AttributeError:
            pass
        self.timer = Timer( stamp, self.hander)
        self.timer.start()
    def hander(self, *args, **kwargs):
        """ find time arrive slot, do it function """
        self.lock.acquire()
        try:
            boxs = self.ready.pop( self.firestamp )
            slots = boxs.values()
        except KeyError:
            slots = []
        for slot in slots:
            if slot.period:
                slot.pc += 1
                if slot.pc != slot.period:
                    slot.fire = slot.interval + slot.fire
                    self._addToReadyList(slot, slot.fire)
            elif slot.period == -1:
                slot.fire = slot.interval + slot.fire
                self._addToReadyList(slot, slot.fire)
        """ """
        self._start()
        self.lock.release()
        for slot in slots:
            try:
                slot.function(slot.args, slot.kwargs)
            except Exception:
                print "slot id %s, timer function fail" % slot.id
    """ operate new timer manager itself """
    def stop(self):
        self.timer.cancel()
    """ new timer manager """
    def add(self, period=0, interval=1, function=None, args=[], kwargs={}):
        """
        period: one time = 0, times = >0, always = -1
        interval: timer fire relative TimerReference
        function: when timer fire, call back function
        args,kwargs: callback function args
        """ 
        interval = int(interval) * self.resolution#seconds
        if interval < self.resolution:
            interval = self.resolution
        slot = Slot( period, interval, function, *args, **kwargs )
        box = dict([(slot.id, slot)])
        self.wait.update(box)
        return slot
    def remove(self, slot):
        if isinstance(slot, Slot):
            self.cancel(slot)
            try:
                self.wait.pop(slot.id)
            except KeyError:
                print "wait dict not has the cancel timer"
    """ timer api """
    def reset(self, slot):
        if isinstance(slot, Slot):
            self.cancel(slot)
            slot.pc = 0
            self.start(slot)
    def start(self, slot):
        def NewTimerStamp(timebase, resolution):
            nowoffset = int(time.time() * 1000) - timebase
            if nowoffset % resolution < resolution / 10:
                currentstamp =  nowoffset / resolution
            else:
                currentstamp = (nowoffset + resolution - 1) / resolution
            return currentstamp * 1000
        global TimerStamp
        if isinstance(slot, Slot):
            firestamp = slot.interval + NewTimerStamp(TimerStamp, self.resolution)
            slot.fire = firestamp
            self.lock.acquire()
            self._addToReadyList(slot, firestamp)
            if self.firestamp > slot.fire:
                self._start()
            self.lock.release()
    def cancel(self, slot):
        if isinstance(slot, Slot):
            try:  
                self.lock.acquire()
                self._delFromReadyList(slot)
                self._start()
                self.lock.release()
            except CancelFail:
                self.lock.release()
def hello( *args, **kargs):
    print args[0], datetime.datetime.now()
if __name__ == "__main__":
    print "start test timer", datetime.datetime.now()
    nt = NewTimer(500)
    t0 = nt.add( -1, 5, hello, [0])
    t1 = nt.add( 4, 7, hello, [1])
    t2 = nt.add( 1, 3, hello, [2])#
    t3 = nt.add( 1, 4, hello, [3])#
    t4 = nt.add( 4, 5, hello, [4])
    t5 = nt.add( 12, 5, hello, [5])#
    t6 = nt.add( 9, 7, hello, [6])
    t7 = nt.add( 1, 8, hello, [7])#
    t8 = nt.add( 40, 1, hello, [8])
    nt.start( t0 )
    nt.start( t1 )
    nt.start( t2 )#
    nt.start( t3 )#
    nt.start( t4 )
    nt.start( t5 )#
    nt.start( t6 )
    nt.start( t7 )#
    nt.start( t8 )
    nt.cancel(t2)
    nt.cancel(t3)
    nt.remove(t5)
    nt.remove(t3)
    time.sleep(3)
    nt.start(t2)
    nt.cancel(t8)
    time.sleep(300)
    nt.stop()
    print "finish test timer", datetime.datetime.now()
Python 相关文章推荐
python 网络爬虫初级实现代码
Feb 27 Python
python文件特定行插入和替换实例详解
Jul 12 Python
python实现识别手写数字 python图像识别算法
Mar 23 Python
Python使用Flask-SQLAlchemy连接数据库操作示例
Aug 31 Python
朴素贝叶斯Python实例及解析
Nov 19 Python
python实现合并两个排序的链表
Mar 03 Python
Python定时任务随机时间执行的实现方法
Aug 14 Python
使用pyinstaller逆向.pyc文件
Dec 20 Python
Python关于反射的实例代码分享
Feb 20 Python
解决python图像处理图像赋值后变为白色的问题
Jun 04 Python
flask框架中的cookie和session使用
Jan 31 Python
Python爬取用户观影数据并分析用户与电影之间的隐藏信息!
Jun 29 Python
python实现猜数字游戏(无重复数字)示例分享
Mar 29 #Python
使用python实现扫描端口示例
Mar 29 #Python
Python Trie树实现字典排序
Mar 28 #Python
python实现探测socket和web服务示例
Mar 28 #Python
python实现目录树生成示例
Mar 28 #Python
python改变日志(logging)存放位置的示例
Mar 27 #Python
使用python删除nginx缓存文件示例(python文件操作)
Mar 26 #Python
You might like
PHP新手上路(七)
2006/10/09 PHP
php中通过DirectoryIterator删除整个目录的方法
2015/03/13 PHP
PHP下载文件的函数实例代码
2016/05/18 PHP
php如何实现不借助IDE快速定位行数或者方法定义的文件和位置
2017/01/17 PHP
php使用include 和require引入文件的区别
2017/02/16 PHP
判断javascript的数据类型(示例代码)
2013/12/11 Javascript
JavaScript中使用ActiveXObject操作本地文件夹的方法
2014/03/28 Javascript
jQuery中focus事件用法实例
2014/12/26 Javascript
基于JavaScript实现鼠标悬浮弹出跟随鼠标移动的带箭头的信息层
2016/01/18 Javascript
Javascript之深入浅出prototype
2017/02/06 Javascript
jQuery时间验证和转换为标准格式的时间格式
2017/03/06 Javascript
JS条形码(一维码)插件JsBarcode用法详解【编码类型、参数、属性】
2017/04/19 Javascript
基于jQuery封装的分页组件
2017/06/26 jQuery
javascript 跨域问题以及解决办法
2017/07/17 Javascript
浅谈vuex 闲置状态重置方案
2018/01/04 Javascript
基于vue-cli 路由 实现类似tab切换效果(vue 2.0)
2019/05/08 Javascript
JavaScript实现多张图片放大镜效果示例【不限定图片尺寸,rem单位】
2019/05/14 Javascript
JS实现点击生成UUID的方法完整实例【基于jQuery】
2019/06/12 jQuery
js实现时分秒倒计时
2019/12/03 Javascript
Vue通过配置WebSocket并实现群聊功能
2019/12/31 Javascript
JS+Canvas实现五子棋游戏
2020/08/26 Javascript
Python多线程实例教程
2014/09/06 Python
Python通过递归遍历出集合中所有元素的方法
2015/02/25 Python
python中获得当前目录和上级目录的实现方法
2017/10/12 Python
TensorFlow如何实现反向传播
2018/02/06 Python
15行Python代码带你轻松理解令牌桶算法
2018/03/21 Python
python+pandas分析nginx日志的实例
2018/04/28 Python
Django Admin设置应用程序及模型顺序方法详解
2020/04/01 Python
Python视频编辑库MoviePy的使用
2020/04/01 Python
C++和python实现阿姆斯特朗数字查找实例代码
2020/12/07 Python
全球销量第一生发产品:Viviscal
2017/12/21 全球购物
澳大利亚第一旅行车和房车配件店:Caravan RV Camping
2020/12/26 全球购物
雷人标语集锦
2014/06/19 职场文书
2014年计生标语
2014/06/23 职场文书
学校运动会广播稿100条
2014/09/14 职场文书
2015年度学校应急管理工作总结
2015/10/22 职场文书