PYTHON 定时器简单封装,基于SCHED

python fresher,轻拍。
在写后台服务时经常会遇到很多定时器的场景,threading.Timer类每实例化一个定时器会有一个新线程去执行,在客户端使用倒是没有问题,如果是服务器端定时器数量多了会影响性能。通常的做法是一个线程按照指定精度发出Ticker,然后检查有没有设置定时器,由则触发;同时要提供SetTimer,KillTimer方法。常用的算法有基于小根堆,时间轮。

本例采用py内置模块sched调度器,sched模块内部使用的优先级队列管理任务,性能未测。

#!/usr/bin/env python3
#-*- coding: utf-8 -*-

import sched
import time
import threading


'''
定时器类,基于sched调度,独立线程服务
'''
class Timer(threading.Thread):
    '''初始化'''
    def __init__(self,interval=0.05):
        threading.Thread.__init__(self)
        self.__sch = sched.scheduler(time.time,time.sleep)
        self.__flag = True
        self.__min_interval = interval

    #overload
    def run(self):
        while self.__flag:
            self.__sch.run()
            time.sleep(self.__min_interval)
            continue

    #overload
    def Start(self):
        self.start()

    def SetTimer(self,interval,func,args):
        return self.__sch.enter(interval,0,func,args)

    def KillTimer(self,event):
        try:
            self.__sch.cancel(event)
        except ValueError as e:
            print("KillTimer err:",e)
        else:
            print("KillTimer unknow err")


    def Destroy(self):
        self.__flag=False

if __name__ == "__main__":
    t=Timer()
    t.Start()

    def func(msg):
        print("timeout ", msg)

    e=t.SetTimer(1,func,("msg",))
    print("set timer",e)
    #t.KillTimer(e)
    t.Destroy()

已知问题:定时器由单线程执行并触发执行,定时器函数的执行会由很大影响。

if __name__ == "__main__":
    t=Timer()
    t.Start()
    def func(msg):
        print("timeout ", msg," now ",time.time())
        time.sleep(2)

    e = t.SetTimer(1, func, ("msg1",))
    e = t.SetTimer(1, func, ("msg2",))

执行结果:

timeout  msg1  now  1513819586.3577309
timeout  msg2  now  1513819588.3586824

func与定时器是同一线程执行,如果新开线程执行func对于耗时少的func又不划算;这点就体现出golang的优势,定时器触发后直接go func(msg),系统开销很小。

原文地址:https://www.cnblogs.com/cqvoip/p/8078651.html