python单线程实现多个定时器示例
单线程实现多个定时器
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 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 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()

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Solution aux problèmes d'autorisation Lors de la visualisation de la version Python dans Linux Terminal Lorsque vous essayez d'afficher la version Python dans Linux Terminal, entrez Python ...

Lorsque vous utilisez la bibliothèque Pandas de Python, comment copier des colonnes entières entre deux frames de données avec différentes structures est un problème courant. Supposons que nous ayons deux dats ...

Dans Python, comment créer dynamiquement un objet via une chaîne et appeler ses méthodes? Il s'agit d'une exigence de programmation courante, surtout si elle doit être configurée ou exécutée ...

Comment Uvicorn écoute-t-il en permanence les demandes HTTP? Uvicorn est un serveur Web léger basé sur ASGI. L'une de ses fonctions principales est d'écouter les demandes HTTP et de procéder ...

Comment enseigner les bases de la programmation novice en informatique dans les 10 heures? Si vous n'avez que 10 heures pour enseigner à l'informatique novice des connaissances en programmation, que choisissez-vous d'enseigner ...

L'article traite des bibliothèques Python populaires comme Numpy, Pandas, Matplotlib, Scikit-Learn, Tensorflow, Django, Flask et Demandes, détaillant leurs utilisations dans le calcul scientifique, l'analyse des données, la visualisation, l'apprentissage automatique, le développement Web et H et H

Fastapi ...

Comment éviter d'être détecté lors de l'utilisation de FiddlereVerywhere pour les lectures d'homme dans le milieu lorsque vous utilisez FiddlereVerywhere ...
