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深入学习之特殊方法与多范式
Aug 31 Python
Python中random模块生成随机数详解
Mar 10 Python
使用Turtle画正螺旋线的方法
Sep 22 Python
Python 十六进制整数与ASCii编码字符串相互转换方法
Jul 09 Python
python实现从pdf文件中提取文本,并自动翻译的方法
Nov 28 Python
Python里字典的基本用法(包括嵌套字典)
Feb 27 Python
django 信号调度机制详解
Jul 19 Python
django-filter和普通查询的例子
Aug 12 Python
python_mask_array的用法
Feb 18 Python
2020最新pycharm汉化安装(python工程狮亲测有效)
Apr 26 Python
python opencv常用图形绘制方法(线段、矩形、圆形、椭圆、文本)
Apr 12 Python
python使用pycharm安装pyqt5以及相关配置
Apr 22 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
用php和MySql来与ODBC数据连接
2006/10/09 PHP
PHP mcrypt可逆加密算法分析
2011/07/19 PHP
PHP设计模式之解释器模式的深入解析
2013/06/13 PHP
zend framework文件上传功能实例代码
2013/12/25 PHP
PHP中使用Imagick实现各种图片效果实例
2015/01/21 PHP
[原创]PHP实现逐行删除文件右侧空格的方法
2015/12/25 PHP
javascript 函数调用规则
2009/08/26 Javascript
jQuery入门第一课 jQuery选择符
2010/03/14 Javascript
ASP.NET jQuery 实例10 动态修改hyperlink的URL值
2012/02/03 Javascript
js 代码优化点滴记录
2012/02/19 Javascript
如何将一个String和多个String值进行比较思路分析
2013/04/22 Javascript
让javascript加载速度倍增的方法(解决JS加载速度慢的问题)
2014/12/12 Javascript
JavaScript中的small()方法使用详解
2015/06/08 Javascript
Knockout自定义绑定创建方法
2015/12/26 Javascript
Bootstrap基本插件学习笔记之折叠(22)
2016/12/08 Javascript
用JS实现简单的登录验证功能
2017/07/28 Javascript
详解vue.js之绑定class和style的示例代码
2017/08/24 Javascript
jquery实现图片跟随鼠标的实例
2017/10/17 jQuery
vue 开发一个按钮组件的示例代码
2018/03/27 Javascript
小程序中canvas的drawImage方法参数使用详解
2019/07/04 Javascript
基于webpack4+vue-cli3项目实现换肤功能
2019/07/17 Javascript
vuex管理状态 刷新页面保持不被清空的解决方案
2019/11/11 Javascript
VSCode Vue开发推荐插件和VSCode快捷键(小结)
2020/08/08 Javascript
通过实例解析jQ Ajax操作相关原理
2020/09/23 Javascript
基于JavaScript实现随机点名器
2021/02/25 Javascript
Python实现将SQLite中的数据直接输出为CVS的方法示例
2017/07/13 Python
python抓取网页内容并进行语音播报的方法
2018/12/24 Python
python爬虫学习笔记之pyquery模块基本用法详解
2020/04/09 Python
C++:memset ,memcpy和strcpy的根本区别
2013/04/27 面试题
Android interview questions
2016/12/25 面试题
什么是继承
2013/12/07 面试题
运动会稿件200字
2014/02/07 职场文书
2015年新学期寄语
2015/02/26 职场文书
共青团优秀团员申请书(范文)
2019/08/15 职场文书
mysql sum(if())和count(if())的用法说明
2022/01/18 MySQL
Redis 报错 error:NOAUTH Authentication required
2022/05/15 Redis