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提取html文件中的特定数据的实现代码
Mar 24 Python
python抓取网页时字符集转换问题处理方案分享
Jun 19 Python
Python重新引入被覆盖的自带function
Jul 16 Python
使用PyCharm配合部署Python的Django框架的配置纪实
Nov 19 Python
Windows上配置Emacs来开发Python及用Python扩展Emacs
Nov 20 Python
对python 中re.sub,replace(),strip()的区别详解
Jul 22 Python
pytorch打印网络结构的实例
Aug 19 Python
基于pycharm实现批量修改变量名
Jun 02 Python
Python如何转换字符串大小写
Jun 04 Python
python switch 实现多分支选择功能
Dec 21 Python
Django中template for如何使用方法
Jan 31 Python
Python pyecharts案例超市4年数据可视化分析
Aug 14 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
支持oicq头像的留言簿(一)
2006/10/09 PHP
php调用KyotoTycoon简单实例
2015/04/02 PHP
详解PHP的Yii框架中日志的相关配置及使用
2015/12/08 PHP
PHP实现向关联数组指定的Key之前插入元素的方法
2017/06/06 PHP
laravel 5异常错误:FatalErrorException in Handler.php line 38的解决
2017/10/12 PHP
Yii框架的布局文件实例分析
2019/09/04 PHP
laravel框架中控制器的创建和使用方法分析
2019/11/23 PHP
学习JS面向对象成果 借国庆发布个最新作品与大家交流
2009/10/03 Javascript
javascript 动态设置已知select的option的value值的代码
2009/12/16 Javascript
js中小数转换整数的方法
2014/01/26 Javascript
jQuery实现自定义下拉列表
2015/01/05 Javascript
基于Jquery插件Uploadify实现实时显示进度条上传图片
2020/03/26 Javascript
AngularJS 模块详解及简单实例
2016/07/28 Javascript
AngularJS 表达式详解及实例代码
2016/09/14 Javascript
利用纯JS实现像素逐渐显示的方法示例
2017/08/14 Javascript
详解React中setState回调函数
2018/06/14 Javascript
微信小程序使用map组件实现解析经纬度功能示例
2019/01/22 Javascript
在vue中使用inheritAttrs实现组件的扩展性介绍
2020/12/07 Vue.js
[56:46]2018DOTA2亚洲邀请赛 3.31 小组赛 B组 VP vs Effect
2018/04/01 DOTA
[01:15:16]DOTA2-DPC中国联赛 正赛 Elephant vs Aster BO3 第一场 1月26日
2021/03/11 DOTA
Android应用开发中Action bar编写的入门教程
2016/02/26 Python
django 常用orm操作详解
2017/09/13 Python
浅析python参数的知识点
2018/12/10 Python
Python中的引用知识点总结
2019/05/20 Python
python3 中的字符串(单引号、双引号、三引号)以及字符串与数字的运算
2019/07/18 Python
详解用python生成随机数的几种方法
2019/08/04 Python
Django框架中间件定义与使用方法案例分析
2019/11/28 Python
Tensorflow 定义变量,函数,数值计算等名字的更新方式
2020/02/10 Python
python实现感知机模型的示例
2020/09/30 Python
用Python自动清理电脑内重复文件,只要10行代码(自动脚本)
2021/01/09 Python
Internet体系结构
2014/12/21 面试题
投资意向书
2014/07/30 职场文书
铣工实训报告
2014/11/05 职场文书
2016年小学生新年寄语
2015/08/18 职场文书
python文本处理的方案(结巴分词并去除符号)
2021/05/26 Python
国庆节到了,利用JS实现一个生成国庆风头像的小工具 详解实现过程
2021/10/05 Javascript