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中reduce()函数的使用方法示例
Sep 29 Python
Python利用pandas计算多个CSV文件数据值的实例
Apr 19 Python
python实现批量修改图片格式和尺寸
Jun 07 Python
python中的tcp示例详解
Dec 09 Python
Python 虚拟空间的使用代码详解
Jun 10 Python
Python通过VGG16模型实现图像风格转换操作详解
Jan 16 Python
给Django Admin添加验证码和多次登录尝试限制的实现
Jul 26 Python
利用python3筛选excel中特定的行(行值满足某个条件/行值属于某个集合)
Sep 04 Python
python 如何利用argparse解析命令行参数
Sep 11 Python
Python如何使用ConfigParser读取配置文件
Nov 12 Python
python实现双向链表原理
May 25 Python
Django框架中视图的用法
Jun 10 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数据缓存的使用说明
2013/05/10 PHP
PHP文件缓存内容保存格式实例分析
2014/08/20 PHP
基于Swoole实现PHP与websocket聊天室
2016/08/03 PHP
CakePHP框架Session设置方法分析
2017/02/23 PHP
Use Word to Search for Files
2007/06/15 Javascript
jquery $(this).attr $(this).val方法使用介绍
2013/10/08 Javascript
深入剖析JavaScript中的枚举功能
2014/03/06 Javascript
教你如何自定义百度分享插件以及bshare分享插件的分享按钮
2014/06/20 Javascript
NodeJS学习笔记之Http模块
2015/01/13 NodeJs
jQuery使用fadeout实现元素渐隐效果的方法
2015/03/27 Javascript
JavaScript jquery及AJAX小结
2016/01/24 Javascript
微信小程序 实战程序简易新闻的制作
2017/01/09 Javascript
微信小程序 设置启动页面的两种方法
2017/03/09 Javascript
Vue插件写、用详解(附demo)
2017/03/20 Javascript
js实现Tab选项卡切换效果
2020/07/17 Javascript
Vue之Vue.set动态新增对象属性方法
2018/02/23 Javascript
uni-app微信小程序登录并使用vuex存储登录状态的思路详解
2019/11/04 Javascript
OpenLayers3实现地图鹰眼以及地图比例尺的添加
2020/09/25 Javascript
[01:16:13]DOTA2-DPC中国联赛 正赛 SAG vs Dragon BO3 第一场 2月22日
2021/03/11 DOTA
Python使用Socket(Https)Post登录百度的实现代码
2012/05/18 Python
Python求两个文本文件以行为单位的交集、并集与差集的方法
2015/06/17 Python
matplotlib绘制符合论文要求的图片实例(必看篇)
2017/06/02 Python
数据清洗--DataFrame中的空值处理方法
2018/07/03 Python
python 搜索大文件的实例代码
2019/07/08 Python
Pandas透视表(pivot_table)详解
2019/07/22 Python
基于Python2、Python3中reload()的不同用法介绍
2019/08/12 Python
如何基于python测量代码运行时间
2019/12/25 Python
Django项目创建及管理实现流程详解
2020/10/13 Python
python解包概念及实例
2021/02/17 Python
联想C++笔试题
2012/06/13 面试题
公司员工的自我评价范例
2013/11/01 职场文书
预备党员思想汇报范文
2013/12/29 职场文书
2014最新自愿离婚协议书范本
2014/11/19 职场文书
特此通知格式
2015/04/27 职场文书
详解MySQL的Seconds_Behind_Master
2021/05/18 MySQL
Mysql数据库表中为什么有索引却没有提高查询速度
2022/02/24 MySQL