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对象体系深入分析
Oct 28 Python
Python中音频处理库pydub的使用教程
Jun 07 Python
PyQt5实现下载进度条效果
Apr 19 Python
Python常见内置高效率函数用法示例
Jul 31 Python
Python设计模式之组合模式原理与用法实例分析
Jan 11 Python
解决pytorch GPU 计算过程中出现内存耗尽的问题
Aug 19 Python
Python中注释(多行注释和单行注释)的用法实例
Aug 28 Python
python Plotly绘图工具的简单使用
Mar 03 Python
详解python百行有效代码实现汉诺塔小游戏(简约版)
Oct 30 Python
Pycharm安装python库的方法
Nov 24 Python
python爬虫快速响应服务器的做法
Nov 24 Python
Python matplotlib可视化之绘制韦恩图
Feb 24 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格式和js json格式 js跨域调用实现代码
2012/09/08 PHP
PHP return语句另类用法不止是在函数中
2014/09/17 PHP
PHP explode()函数的几个应用和implode()函数有什么区别
2015/11/05 PHP
PHP 返回13位时间戳的实现代码
2016/05/13 PHP
PHP 序列化和反序列化函数实例详解
2020/07/18 PHP
php+redis消息队列实现抢购功能
2018/02/08 PHP
laravel 验证错误信息到 blade模板的方法
2019/09/29 PHP
JSON 入门指南 想了解json的朋友可以看下
2009/08/26 Javascript
window.returnValue使用方法示例介绍
2014/07/03 Javascript
jQuery.parseJSON(json)将JSON字符串转换成js对象
2014/07/27 Javascript
Jquery仿IGoogle实现可拖动窗口示例代码
2014/08/22 Javascript
JavaScript之Object类型介绍
2015/04/01 Javascript
jQuery实现仿腾讯迷你首页选项卡效果代码
2015/09/17 Javascript
MVC Ajax Helper或Jquery异步加载部分视图
2015/11/29 Javascript
全面解析Bootstrap排版使用方法(标题)
2015/11/30 Javascript
js前端面试题及答案整理(一)
2016/08/26 Javascript
jQuery实现6位数字密码输入框
2016/12/29 Javascript
vue单个组件实现无限层级多选菜单功能
2018/04/10 Javascript
jQuery AJAX 方法success()后台传来的4种数据详解
2018/08/08 jQuery
js中async函数结合promise的小案例浅析
2019/04/14 Javascript
Vue.js使用axios动态获取response里的data数据操作
2020/09/08 Javascript
[02:11]DOTA2上海特级锦标赛主赛事第二日RECAP
2016/03/04 DOTA
TensorFlow实现卷积神经网络CNN
2018/03/09 Python
使用Python快乐学数学Github万星神器Manim简介
2019/08/07 Python
Python倒排索引之查找包含某主题或单词的文件
2019/11/13 Python
Python tornado上传文件的功能
2020/03/26 Python
python 画图 图例自由定义方式
2020/04/17 Python
纯css3使用vw和vh实现自适应的方法
2018/02/09 HTML / CSS
HTML5 表单验证失败的提示语问题
2017/07/13 HTML / CSS
Under Armour西班牙官网:美国知名的高端功能性运动品牌
2018/12/12 全球购物
软件缺陷的分类都有哪些
2014/08/22 面试题
个性车贴标语
2014/06/24 职场文书
详解CSS开发过程中的20个快速提升技巧
2021/05/21 HTML / CSS
Python标准库之typing的用法(类型标注)
2021/06/02 Python
go语言中http超时引发的事故解决
2021/06/02 Golang
Java获取e.printStackTrace()打印的信息方式
2021/08/07 Java/Android