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检测远程服务器tcp端口的方法
Mar 14 Python
详解Python2.x中对Unicode编码的使用
Apr 03 Python
socket + select 完成伪并发操作的实例
Aug 15 Python
神经网络python源码分享
Dec 15 Python
python MySQLdb使用教程详解
Mar 20 Python
详解python配置虚拟环境
Apr 08 Python
Python秒算24点实现及原理详解
Jul 29 Python
python使用minimax算法实现五子棋
Jul 29 Python
Python turtle绘画象棋棋盘
Aug 21 Python
Python unittest单元测试openpyxl实现过程解析
May 27 Python
详解Pytorch显存动态分配规律探索
Nov 17 Python
python工具快速为音视频自动生成字幕(使用说明)
Jan 27 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去除数组中重复的元素并按键名排序函数
2008/08/18 PHP
php获取一个变量的名字的方法
2014/09/05 PHP
php防止sql注入之过滤分页参数实例
2014/11/03 PHP
php实现Session存储到Redis
2015/11/11 PHP
如何用javascript控制上传文件的大小
2006/10/26 Javascript
JavaScript脚本语言在网页中的简单应用
2007/05/13 Javascript
JS面向对象编程浅析
2011/08/28 Javascript
基于JQuery的一句话搞定手风琴菜单
2012/09/14 Javascript
Jquery 选中表格一列并对表格排序实现原理
2012/12/15 Javascript
js 文本滚动效果的实例代码
2013/08/17 Javascript
jQuery中:checkbox选择器用法实例
2015/01/03 Javascript
理解javascript中的原型和原型链
2015/07/30 Javascript
windows下安装nodejs及框架express
2015/08/07 NodeJs
jquery easyui validatebox remote的使用详解
2016/11/09 Javascript
jQuery源码解读之extend()与工具方法、实例方法详解
2017/03/30 jQuery
微信小程序开发之改变data中数组或对象的某一属性值
2018/07/05 Javascript
微信小程序首页的分类功能和搜索功能的实现思路及代码详解
2018/09/11 Javascript
在vue中获取token,并将token写进header的方法
2018/09/26 Javascript
微信小程序动态添加view组件的实例代码
2019/05/23 Javascript
使用js实现一个简单的滚动条过程解析
2019/09/10 Javascript
微信小程序开发(一):服务器获取数据列表渲染操作示例
2020/06/01 Javascript
vue video和vue-video-player实现视频铺满教程
2020/10/30 Javascript
PYTHON正则表达式 re模块使用说明
2011/05/19 Python
Python实现读取目录所有文件的文件名并保存到txt文件代码
2014/11/22 Python
Python生成器(Generator)详解
2015/04/13 Python
python图像处理之镜像实现方法
2015/05/30 Python
python实现redis三种cas事务操作
2017/12/19 Python
python删除某个字符
2018/03/19 Python
python实现nao机器人身体躯干和腿部动作操作
2019/04/29 Python
Python整数对象实现原理详解
2019/07/01 Python
python根据完整路径获得盘名/路径名/文件名/文件扩展名的方法
2020/04/22 Python
html5 Canvas画图教程(6)—canvas里画曲线之arcTo方法
2013/01/09 HTML / CSS
this关键字的含义
2015/04/08 面试题
朝花夕拾读书笔记
2015/06/29 职场文书
HTML5页面音频自动播放的实现方式
2021/06/21 HTML / CSS
React如何创建组件
2021/06/27 Javascript