详解Python 多线程 Timer定时器/延迟执行、Event事件
作者:ihoneysec 发布时间:2022-09-04 11:12:52
Timer继承子Thread类,是Thread的子类,也是线程类,具有线程的能力和特征。这个类用来定义多久执行一个函数。
它的实例是能够延迟执行目标函数的线程,在真正执行目标函数之前,都可以cancel它。
Timer源码:
class Timer(Thread):
def __init__(self, interval, function, args=None, kwargs=None):
Thread.__init__(self)
self.interval = interval
self.function = function
self.args = args if args is not None else []
self.kwargs = kwargs if kwargs is not None else {}
self.finished = Event()
def cancel(self):
"""Stop the timer if it hasn't finished yet."""
self.finished.set()
def run(self):
self.finished.wait(self.interval)
if not self.finished.is_set():
self.function(*self.args, **self.kwargs)
self.finished.set()
Timer类使用方法与Thread定义子线程一样,interval传入间隔时间,function传入线程执行的函数,args和kwargs传入函数的参数。
提前cancel:
import threading
import time
def add(x,y):
print(x+y)
t = threading.Timer(10,add,args=(4,5))
t.start()
time.sleep(2)
t.cancel()
print("===end===")
运行结果:
===end===
start方法执行之后,Timer对象会处于等待状态,等待10秒之后会执行add函数。同时,在执行add函数之前的等待阶段,主线程使用了子线程的cancel方法,就会跳过执行函数结束。
使用event 事件实现Timer计时器:
import threading
import logging
import time
logging.basicConfig(level=logging.INFO)
# class MyTimer(threading.Thread):
class MyTimer:
def __init__(self,interval,fn,args=None):
self.interval = interval
self.fn = fn
self.args = args
self.event = threading.Event()
def start(self):
threading.Thread(target=self.__do).start()
def cancel(self):
self.event.set()
def __do(self):
self.event.wait(self.interval)
if not self.event.is_set():
self.fn(*self.args)
def add(x,y):
logging.warning(x+y)
t = MyTimer(5,add,(4,5))
t.start()
# time.sleep(2)
# t.cancel()
运行结果:
WARNING:root:9
Event事件,是线程间通信机制中最简单的实现,使用一个内部的标记flag,通过flag的True或False的变化来进行操作。
Event源码:
class Event:
def __init__(self):
self._cond = Condition(Lock())
self._flag = False
def _reset_internal_locks(self):
self._cond.__init__(Lock())
def is_set(self):
return self._flag
isSet = is_set
def set(self):
with self._cond:
self._flag = True
self._cond.notify_all()
def clear(self):
with self._cond:
self._flag = False
def wait(self, timeout=None):
with self._cond:
signaled = self._flag
if not signaled:
signaled = self._cond.wait(timeout)
return signaled
Event 方法:
•set() flag设置为True
•clear() flag设置为False
•is_set() flag是否为True,返回布尔值
•wait(timeout=None) 设置等待flag变为True的时长,None为无限等待。等到了返回True,未等到超时了就返回False。
举例:
老板雇佣了一个工人,让他生产杯子,老板一直等着工人,直到生产了10个杯子。
import threading
import logging
import time
logging.basicConfig(level=logging.INFO)
cups = []
event = threading.Event()#event对象
def boss(e:threading.Event):
if e.wait(30):#最多等待30秒
logging.info('Good job.')
def worker(n,e:threading.Event):
while True:
time.sleep(0.5)
cups.append(1)
logging.info('make 1')
if len(cups) >=n:
logging.info('I finished my job. {}'.format(len(cups)))
e.set()#flag设置为True
break
b = threading.Thread(target=boss,name='boos',args=(event,))
w = threading.Thread(target=worker,args=(10,event))
w.start()
b.start()
运行结果:
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:make 1
INFO:root:I finished my job. 10
INFO:root:Good job.
老板和工人使用同一个Event对象的标记flag。
老板wait()设置为最多等待30秒,等待flag变为True,工人在做够10杯子时,将flag设置为True,工人必须在30秒之内没有做好杯子。
wait的使用:
import threading
import logging
logging.basicConfig(level=logging.INFO)
def do(event:threading.Event,interval:int):
while not event.wait(interval): # not event.wait(1) = True
logging.info('To do sth.')
e = threading.Event()
t = threading.Thread(target=do,args=(e,1))
t.start()
e.wait(10) # 也可以使用time.sleep(10)
e.set()
print('Man Exit.')
运行结果:
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
INFO:root:To do sth.
Man Exit.
wait与sleep的区别是:wait会主动让出时间片,其它线程可以被调度,而sleep会占用时间片不让出。
小结:
Timer定时器继承自Thread类,也是线程类。它的作用是等待n秒钟之后执行某个目标函数,可以使用cancel提前取消。
Event事件是通过True和False维护一个flag标记值,通过这个标记的值来决定做某事,wait()方法可以设置最长等待flag设置为Ture的时长,超时还未设置为True就返回False。
PS:下面看下python之定时器Timer
timer类
Timer(定时器)是Thread的派生类,用于在指定时间后调用一个方法。
构造方法:
Timer(interval, function, args=[], kwargs={})
interval: 指定的时间
function: 要执行的方法
args/kwargs: 方法的参数
实例方法:
Timer从Thread派生,没有增加实例方法。
例子一:
# encoding: UTF-8
import threading
def func():
print 'hello timer!'
timer = threading.Timer(5, func)
timer.start()
线程延迟5秒后执行。
总结
以上所述是小编给大家介绍的详解Python 多线程 Timer定时器/延迟执行、Event事件,网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
来源:https://www.cnblogs.com/i-honey/p/8051680.html


猜你喜欢
- 1、显式等待它指定要查找的节点,然后指定一个最长的等待时间,如果规定时间内加载出来了这个节点,就返回查找的节点;如果规定时间内没有加载出该节
- 加载模型并查看网络加载模型,以vgg19为例。打开终端> pythonPython 3.7.2 (tags/v3.7.2:9a3ffc
- 正文在平时的开发过程中,我们会遇到一些特殊的应用场景,如果你想要在执行某种操作之前或者之后你能够得到通知,并对其进行一些你想要的操作时,你就
- 标题: Microsoft SQL Server Management Studio ---------------------------
- asp.net和php哪个更好?在.net之前,微软的是ASP。在微软的大力推广下,其看起来还是很有前途的。但现在,微软想推广asp.net
- 目录背景目的拆分前流程设计目录结构设计存在的问题拆分后流程设计目录结构设计解决的问题关键代码总结其他实现方式背景由于之前的数据库防火墙产品与
- 在pyhton中,经常会用到input()语句,但是input()语句输入的内容只能时字符串类型,而我们经常要输入int类型的数据等,那么就
- 前言可选链操作符(?.)允许读取位于链接对象链身处的属性的值,而不必明确验证链中的每个引用是否有效。不同之处在于,在引用为空(null或者u
- #!/usr/bin/env python# -*- coding:utf-8 -*-#导入random和string模块import ra
- 1.引入库需要用到3个类,ElementTree,Element以及建立子类的包装类SubElementfrom xml.etree.Ele
- MySQL安装文件分为两种,一种是msi格式的,一种是zip格式的。点击进入:下载地址1.下面是msi的下载和安装的步骤点击进去之后根据自己
- 一、前言最近趁空闲之余,在对MySQL数据库进行插入数据测试,对于如何快速插入数据的操作无从下手,在仅1W数据量的情况下,竟花费接近47s,
- 本文实例讲述了JavaScript实现模仿桌面窗口的方法。分享给大家供大家参考。具体如下:这里使用JS模仿了桌面窗口的移动、八个方向的缩放、
- PHP计算字符串用strlen()只能得到字符串长度,不是宽高像素,使用到了php函数ImageTTFBBox(),就可以根据字体的大小和所
- 由于最近有个任务需要在python环境下跑,项目是python3.6 + tensorflow1.3.1.现总结安装环境:卸载Python3
- 在写移动端页面的时候,弹出遮罩层后,我们仍然可以滚动页面。vue中提供 @touchmove.prevent 方法可以完美解决这个问题<
- 字符串的IndexOf()方法搜索在该字符串上是否出现了作为参数传递的字符串,如果找到字符串,则返回字符的起始位置 (0表示第一个字符,1表
- 用for循环和海龟绘图实现漂亮的螺旋线A.课程内容本节课通过绘制复杂的螺旋线来深入学习for循环和range()函数的用法。深入了解循环的程
- 使用OpenCV's Haar cascades作为人脸检测,因为他做好了库,我们只管使用。代码简单,除去注释,总共有效代码只有10
- http://pyhdfs.readthedocs.io/en/latest/1:安装由于是windows环境(linux其实也一样),只要