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实现计算倒数的方法
Jul 11 Python
python 捕获shell脚本的输出结果实例
Jan 04 Python
Python实现的文本编辑器功能示例
Jun 30 Python
彻底理解Python list切片原理
Oct 27 Python
python对列进行平移变换的方法(shift)
Jan 10 Python
Python + OpenCV 实现LBP特征提取的示例代码
Jul 11 Python
Python 网络编程之TCP客户端/服务端功能示例【基于socket套接字】
Oct 12 Python
Python random模块制作简易的四位数验证码
Feb 01 Python
Django框架配置mysql数据库实现过程
Apr 22 Python
详解Windows下PyCharm安装Numpy包及无法安装问题解决方案
Jun 18 Python
Python连接Mysql进行增删改查的示例代码
Aug 03 Python
Python3中最常用的5种线程锁实例总结
Jul 07 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 数学运算验证码实现代码
2009/10/11 PHP
php下获取Discuz论坛登录用户名、用户组、用户ID等信息的实现代码
2010/12/29 PHP
PHP常见数组排序方法小结
2018/08/20 PHP
JQuery 表单中textarea字数限制实现代码
2009/12/07 Javascript
javascript 广告后加载,加载完页面再加载广告
2010/11/25 Javascript
js 调用父窗口的具体实现代码
2013/07/15 Javascript
javascript框架设计之类工厂
2015/06/23 Javascript
jQuery中text() val()和html()的区别实例详解
2016/06/28 Javascript
浅谈js中子页面父页面方法 变量相互调用
2016/08/04 Javascript
JavaScript实现替换字符串中最后一个字符的方法
2017/03/07 Javascript
关于vue.js v-bind 的一些理解和思考
2017/06/06 Javascript
微信小程序实现点击文字页面跳转功能【附源码下载】
2017/12/12 Javascript
详解Ant Design of React的安装和使用方法
2018/12/27 Javascript
JS隐藏号码中间4位代码实例
2019/04/09 Javascript
Node使用Nodemailer发送邮件的方法实现
2020/02/24 Javascript
原生js实现日历效果
2020/03/02 Javascript
python实现微信远程控制电脑
2018/02/22 Python
用python实现刷点击率的示例代码
2019/02/21 Python
Django RBAC权限管理设计过程详解
2019/08/06 Python
如何基于python测量代码运行时间
2019/12/25 Python
Python爬取新型冠状病毒“谣言”新闻进行数据分析
2020/02/16 Python
详解pytorch tensor和ndarray转换相关总结
2020/09/03 Python
Python的scikit-image模块实例讲解
2020/12/30 Python
H5 video poster属性设置视频封面的方法
2020/05/25 HTML / CSS
巴西化妆品商店:Lojas Rede
2019/07/26 全球购物
中国一家综合的外贸B2C电子商务网站:DealeXtreme(DX)
2020/03/10 全球购物
extern是什么意思
2016/03/10 面试题
十佳大学生事迹材料
2014/01/29 职场文书
高考励志标语
2014/06/05 职场文书
学生检讨书怎么写
2014/10/09 职场文书
2014年教师工作总结
2014/11/10 职场文书
财务会计岗位职责
2015/02/03 职场文书
2015年计划生育责任书
2015/05/08 职场文书
总经理聘用协议书
2015/09/21 职场文书
详解Laravel制作API接口
2021/05/31 PHP
vue/cli 配置动态代理无需重启服务的方法
2022/05/20 Vue.js