Python中使用threading.Event协调线程的运行详解


Posted in Python onMay 02, 2020

threading.Event机制类似于一个线程向其它多个线程发号施令的模式,其它线程都会持有一个threading.Event的对象,这些线程都会等待这个事件的“发生”,如果此事件一直不发生,那么这些线程将会阻塞,直至事件的“发生”。

对此,我们可以考虑一种应用场景(仅仅作为说明),例如,我们有多个线程从Redis队列中读取数据来处理,这些线程都要尝试去连接Redis的服务,一般情况下,如果Redis连接不成功,在各个线程的代码中,都会去尝试重新连接。

如果我们想要在启动时确保Redis服务正常,才让那些工作线程去连接Redis服务器,那么我们就可以采用threading.Event机制来协调各个工作线程的连接操作:

主线程中会去尝试连接Redis服务,如果正常的话,触发事件,各工作线程会尝试连接Redis服务。

为此,我们可以写下如下的程序:

import threading
import time
import logging
 
logging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s) %(message)s',)
 
def worker(event):
  logging.debug('Waiting for redis ready...')
  event.wait()
  logging.debug('redis ready, and connect to redis server and do some work [%s]', time.ctime())
  time.sleep(1)
 
readis_ready = threading.Event()
t1 = threading.Thread(target=worker, args=(readis_ready,), name='t1')
t1.start()
 
t2 = threading.Thread(target=worker, args=(readis_ready,), name='t2')
t2.start()
 
logging.debug('first of all, check redis server, make sure it is OK, and then trigger the redis ready event')
time.sleep(3) # simulate the check progress 
readis_ready.set()

运行这个程序:

(t1    ) Waiting for redis ready...
(t2    ) Waiting for redis ready...
(MainThread) first of all, check redis server, make sure it is OK, and then trigger the redis ready event
(t2    ) redis ready, and connect to redis server and do some work [Wed Nov 5 12:45:03 2014]
(t1    ) redis ready, and connect to redis server and do some work [Wed Nov 5 12:45:03 2014]

t1和t2线程开始的时候都阻塞在等待redis服务器启动的地方,一旦主线程确定了redis服务器已经正常启动,那么会触发redis_ready事件,各个工作线程就会去连接redis去做相应的工作。

threading.Event的wait方法还接受一个超时参数,默认情况下如果事件一直没有发生,wait方法会一直阻塞下去,而加入这个超时参数之后,如果阻塞时间超过这个参数设定的值之后,wait方法会返回。

对应于上面的应用场景,如果Redis服务器一致没有启动,我们希望子线程能够打印一些日志来不断地提醒我们当前没有一个可以连接的Redis服务,我们就可以通过设置这个超时参数来达成这样的目的:

import threading
import time
import logging
 
logging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s) %(message)s',)
 
def worker(event):
  while not event.is_set():
    logging.debug('Waiting for redis ready...')
    event.wait(1)
  logging.debug('redis ready, and connect to redis server and do some work [%s]', time.ctime())
  time.sleep(1)
 
readis_ready = threading.Event()
t1 = threading.Thread(target=worker, args=(readis_ready,), name='t1')
t1.start()
 
t2 = threading.Thread(target=worker, args=(readis_ready,), name='t2')
t2.start()
 
logging.debug('first of all, check redis server, make sure it is OK, and then trigger the redis ready event')
time.sleep(3) # simulate the check progress 
readis_ready.set()

与前面的无限阻塞版本唯一的不同就是,我们在工作线程中加入了一个while循环,直到redis_ready事件触发之后才会结束循环,wait方法调用会在1秒的超时后返回,这样,我们就可以看到各个工作线程在系统启动的时候等待redis_ready的同时,会记录一些状态信息。

以下是这个程序的运行结果:

(t1    ) Waiting for redis ready...
(t2    ) Waiting for redis ready...
(MainThread) first of all, check redis server, make sure it is OK, and then trigger the redis ready event
(t2    ) Waiting for redis ready...
(t1    ) Waiting for redis ready...
(t2    ) Waiting for redis ready...
(t1    ) Waiting for redis ready...
(t2    ) redis ready, and connect to redis server and do some work [Wed Nov 5 13:55:46 2014]
(t1    ) redis ready, and connect to redis server and do some work [Wed Nov 5 13:55:46 2014]

这样,我们就可以在等待Redis服务启动的同时,看到工作线程里正在等待的情况。

以上这篇Python中使用threading.Event协调线程的运行详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python实现LRU算法的2种方法
Jun 24 Python
python itchat实现微信好友头像拼接图的示例代码
Aug 14 Python
python如何将图片转换为字符图片
Aug 19 Python
python使用Matplotlib画条形图
Mar 25 Python
python并发和异步编程实例
Nov 15 Python
Python中的十大图像处理工具(小结)
Jun 10 Python
python+opencv边缘提取与各函数参数解析
Mar 09 Python
200行python代码实现贪吃蛇游戏
Apr 24 Python
python实现发送QQ邮件(可加附件)
Dec 23 Python
如何编写python的daemon程序
Jan 07 Python
解决Django transaction进行事务管理踩过的坑
Apr 24 Python
Python创建SQL数据库流程逐步讲解
Sep 23 Python
浅谈Python3多线程之间的执行顺序问题
May 02 #Python
python继承threading.Thread实现有返回值的子类实例
May 02 #Python
Python3-异步进程回调函数(callback())介绍
May 02 #Python
浅谈Python中threading join和setDaemon用法及区别说明
May 02 #Python
判断Threading.start新线程是否执行完毕的实例
May 02 #Python
python中threading开启关闭线程操作
May 02 #Python
浅谈python3打包与拆包在函数的应用详解
May 02 #Python
You might like
用Socket发送电子邮件
2006/10/09 PHP
PHP 读取和修改大文件的某行内容的代码
2009/10/30 PHP
PhpStorm 2020.3:新增开箱即用的PHP 8属性(推荐)
2020/10/30 PHP
JAVASCRIPT  THIS详解 面向对象
2009/03/25 Javascript
ExtJS4如何自动生成控制grid的列显示、隐藏的checkbox
2014/05/02 Javascript
一个用jquery写的判断div滚动条到底部的方法【推荐】
2016/04/29 Javascript
全国省市二级联动下拉菜单 js版
2016/05/10 Javascript
限制文本框只能输入数字||只能是数字和小数点||只能是整数和浮点数
2016/05/27 Javascript
jQuery使用deferreds串行多个ajax请求
2016/08/22 Javascript
JS实现“隐藏与显示”功能(多种方法)
2016/11/24 Javascript
JS跨域请求外部服务器的资源
2017/02/06 Javascript
Vue服务端渲染和Vue浏览器端渲染的性能对比(实例PK )
2017/03/31 Javascript
Jquery+Ajax+xml实现中国地区选择三级联动菜单效果(推荐)
2017/06/09 jQuery
Angular实现响应式表单
2017/08/04 Javascript
JS+Canvas绘制动态时钟效果
2017/11/10 Javascript
select标签设置默认选中的选项方法
2018/03/02 Javascript
vue组件中的样式属性scoped实例详解
2018/10/30 Javascript
推荐15个最好用的JavaScript代码压缩工具
2019/02/13 Javascript
vue视频播放暂停代码
2019/11/08 Javascript
nodejs中使用archive压缩文件的实现代码
2019/11/26 NodeJs
vue 获取url参数、get参数返回数组的操作
2020/11/12 Javascript
[04:22]DOTA2上海特级锦标赛主赛事第四日TOP10
2016/03/06 DOTA
举例讲解Python的Tornado框架实现数据可视化的教程
2015/05/02 Python
Python paramiko模块的使用示例
2018/04/11 Python
python+unittest+requests实现接口自动化的方法
2018/11/29 Python
使用pyshp包进行shapefile文件修改的例子
2019/12/06 Python
浅谈python多线程和多线程变量共享问题介绍
2020/04/17 Python
opencv 形态学变换(开运算,闭运算,梯度运算)
2020/07/07 Python
一个SQL面试题
2014/08/21 面试题
美德少年事迹材料
2014/01/23 职场文书
高中生操行评语大全
2014/04/25 职场文书
环境保护与污染治理求职信
2014/07/16 职场文书
迎新生标语大全
2014/10/06 职场文书
教师节座谈会主持词
2015/07/03 职场文书
2019广播稿怎么写
2019/04/17 职场文书
使用CSS定位HTML元素的实现方法
2022/07/07 HTML / CSS