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

#!/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()

本条技术文章来源于互联网,如果无意侵犯您的权益请点击此处反馈版权投诉

本文系统来源:php中文网

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值