想要实现:一个函数 查看指定端口的进程是否运行正常。该函数需要每隔几分钟循环地执行。
Timer(interval, function, args=[], kwargs={})
最简单的方法就是在function中注册Timer, 每隔interval 产生一个线程,线程执行function,以达到循环的效果。interval的单位是秒。
示例:
from threading import Timer
def hello():
print "hello, world"
t = Timer(10.0, hello)
t.start()
- 我最开始用的就是这个方法,简单易懂。但是发现这样做很危险:
Timer是threading的派生类,本质是一个thread,每次调用function就产生一个Timer线程,然后过一段时间再回收。然而,如果时间间隔较小(例如:几秒,一分钟),系统还没来得及回收线程的话,就会导致线程数增多,占用cpu和系统内存,甚至会把cpu跑满. - 解决方法:把interval设的很大很大,几十分钟或者几小时。或者直接换个方法吧
重写RepeatingTimer 类的run方法
在python2里的_Timer(相当于python3的Timer)是threading的子类。重写如下:
from threading import _Timer
def hello():
print "hello, world"
class RepeatingTimer(_Timer):
def run(self):
while not self.finished.is_set():
self.function(*self.args, **self.kwargs)
self.finished.wait(self.interval)
t = RepeatingTimer(10.0, hello)
t.start()
为了理解以上重写的RepeatingTimer,再看_Timer的原函数:
class _Timer(Thread):
"""Call a function after a specified number of seconds:
t = Timer(30.0, f, args=[], kwargs={})
t.start()
t.cancel() # stop the timer's action if it's still waiting
"""
def __init__(self, interval, function, args=[], kwargs={}):
Thread.__init__(self)
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.finished = Event()
def run(self):
self.finished.wait(self.interval)
if not self.finished.is_set():
self.function(*self.args, **self.kwargs)
self.finished.set()
def cancel(self):
"""Stop the timer if it hasn't finished yet"""
self.finished.set()
- 可以看出
self.finished
是一个 threading.Event 对象,其中包含一个默认值为False的flag,event.set()函数可以将flag变成True。self.finished.is_set()
指的是判断该线程有没有结束,is_set()函数获取flag的值,返回True或False。
原来的_Timer.run()只执行一次function,而RepeatingTimer.run()是一个while循环,所以只要 flag是False就会一直执行function,然后wait直到interval结束。 - 这样的好处就是:只有一个线程在循环,不会产生多个线程(貌似对CPU占用没什么影响)。当想要结束时可以调用t.cancel()函数。
参考: python如何让程序定时循环执行.
Python threading中event的使用.