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的Tornado框架实现异步非阻塞访问数据库的示例
Jun 30 Python
机器学习python实战之决策树
Nov 01 Python
python正则中最短匹配实现代码
Jan 16 Python
Python搭建FTP服务器的方法示例
Jan 19 Python
python安装twisted的问题解析
Aug 21 Python
Python如何爬取微信公众号文章和评论(基于 Fiddler 抓包分析)
Jun 28 Python
Python Des加密解密如何实现软件注册码机器码
Jan 08 Python
Python装饰器结合递归原理解析
Jul 02 Python
Matlab中plot基本用法的具体使用
Jul 17 Python
Python爬取微信小程序Charles实现过程图解
Sep 29 Python
Python制作运行进度条的实现效果(代码运行不无聊)
Feb 24 Python
pandas中关于apply+lambda的应用
Feb 28 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 float不四舍五入截取浮点型字符串方法总结
2013/10/28 PHP
php实现可逆加密的方法
2015/08/11 PHP
PHP 根据key 给二维数组分组
2016/12/09 PHP
浅谈php(codeigniter)安全性注意事项
2017/04/06 PHP
Javascript的IE和Firefox兼容性汇编
2006/07/01 Javascript
Javascript 强制类型转换函数
2009/05/17 Javascript
javascript来定义类的规范小结
2010/11/19 Javascript
IE下写xml文件的两种方式(fso/saveAs)
2013/08/05 Javascript
JQuery报错Uncaught TypeError: Illegal invocation的处理方法
2015/03/13 Javascript
jQuery在页面加载时动态修改图片尺寸的方法
2015/03/20 Javascript
使用HTML+CSS+JS制作简单的网页菜单界面
2015/07/27 Javascript
AngularJS入门教程之路由与多视图详解
2016/08/19 Javascript
JS表单验证方法实例小结【电话、身份证号、Email、中文、特殊字符、身份证号等】
2017/02/14 Javascript
浅谈js中用$(#ID)来作为选择器的问题(id重复的时候)
2017/02/14 Javascript
angular.js+node.js实现下载图片处理详解
2017/03/31 Javascript
AngularJS基于provider实现全局变量的读取和赋值方法
2017/06/28 Javascript
js实现QQ面板拖拽效果(慕课网DOM事件探秘)(全)
2017/09/19 Javascript
ExtJs使用自定义插件动态保存表头配置(隐藏或显示)
2018/09/25 Javascript
express框架中使用jwt实现验证的方法
2019/08/25 Javascript
使用easyui从servlet传递json数据到前端页面的两种方法
2019/09/05 Javascript
解决layui table表单提示数据接口请求异常的问题
2019/09/24 Javascript
[02:51]DOTA2战队出征照拍摄花絮 TI3明星化身时尚男模
2013/07/22 DOTA
Python translator使用实例
2008/09/06 Python
Python文件操作类操作实例详解
2014/07/11 Python
windows下python安装paramiko模块和pycrypto模块(简单三步)
2017/07/06 Python
Numpy 改变数组维度的几种方法小结
2018/08/02 Python
Python中的 sort 和 sorted的用法与区别
2019/08/10 Python
python文件编写好后如何实践
2020/07/07 Python
Python描述数据结构学习之哈夫曼树篇
2020/09/07 Python
Marks & Spencer爱尔兰:英国马莎百货
2016/04/20 全球购物
欧洲最大的美妆零售网站:Feelunique
2017/01/14 全球购物
美国复古街头服饰精品店:Need Supply Co.
2017/02/22 全球购物
澳大利亚最大的女装零售商:Millers
2017/09/10 全球购物
Lampenwelt德国:欧洲领先的灯具和照明在线商店
2018/08/05 全球购物
发布会邀请函
2015/01/31 职场文书
干货!开幕词的写作方法
2019/04/02 职场文书