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 version 2.7 required, which was not found in the registry
Aug 26 Python
django模型中的字段和model名显示为中文小技巧分享
Nov 18 Python
pandas apply 函数 实现多进程的示例讲解
Apr 20 Python
Python使用sort和class实现的多级排序功能示例
Aug 15 Python
在linux下实现 python 监控usb设备信号
Jul 03 Python
python将excel转换为csv的代码方法总结
Jul 03 Python
Python实现隐马尔可夫模型的前向后向算法的示例代码
Dec 31 Python
使用TensorFlow对图像进行随机旋转的实现示例
Jan 20 Python
tensorflow-gpu安装的常见问题及解决方案
Jan 20 Python
Python collections.deque双边队列原理详解
Oct 05 Python
python批量创建变量并赋值操作
Jun 03 Python
Python内置数据结构列表与元组示例详解
Aug 04 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生成及获取JSON文件的方法
2016/08/23 PHP
jQuery拖拽 &amp; 弹出层 介绍与示例
2013/12/27 Javascript
javascript日期对象格式化为字符串的实现方法
2014/01/14 Javascript
JavaScript中九种常用排序算法
2014/09/02 Javascript
JQuery判断radio是否选中并获取选中值的示例代码
2014/10/17 Javascript
javascript工厂方式定义对象
2014/12/26 Javascript
在Mac OS下使用Node.js的简单教程
2015/06/24 Javascript
JavaScript在网页中画圆的函数arc使用方法
2015/11/13 Javascript
如何用JS判断两个数字的大小
2016/07/21 Javascript
详解Angular的8个主要构造块
2017/06/20 Javascript
React复制到剪贴板的示例代码
2017/08/22 Javascript
关于定制FileField中的上传文件名称问题
2017/08/22 Javascript
js数组实现权重概率分配
2017/09/12 Javascript
Vue ElementUi同时校验多个表单(巧用new promise)
2018/06/06 Javascript
D3.js实现拓扑图的示例代码
2018/06/30 Javascript
Vue+ElementUI项目使用webpack输出MPA的方法
2019/08/27 Javascript
javascript实现简易的计算器
2020/01/17 Javascript
浅谈vue使用axios的回调函数中this不指向vue实例,为undefined
2020/09/21 Javascript
[48:00]完美世界DOTA2联赛循环赛 Forest vs Inki BO2第二场 11.04
2020/11/04 DOTA
Python脚本处理空格的方法
2016/08/08 Python
python输入错误密码用户锁定实现方法
2017/11/27 Python
python3+PyQt5+Qt Designer实现扩展对话框
2018/04/20 Python
对Python 2.7 pandas 中的read_excel详解
2018/05/04 Python
详解django中使用定时任务的方法
2018/09/27 Python
pyqt5 tablewidget 利用线程动态刷新数据的方法
2019/06/17 Python
Django Channels 实现点对点实时聊天和消息推送功能
2019/07/17 Python
用Python抢火车票的简单小程序实现解析
2019/08/14 Python
Python新手学习函数默认参数设置
2020/06/03 Python
matplotlib运行时配置(Runtime Configuration,rc)参数rcParams解析
2021/01/05 Python
什么是反射?如何实现反射?
2016/07/25 面试题
学员自我鉴定
2014/03/19 职场文书
心理健康活动总结
2014/04/30 职场文书
校园广播稿100字
2014/10/06 职场文书
酒店人事专员岗位职责
2015/04/07 职场文书
2015年机关纠风工作总结
2015/05/15 职场文书
边城读书笔记
2015/06/29 职场文书