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 常用string函数详解
May 30 Python
解决python3中自定义wsgi函数,make_server函数报错的问题
Nov 21 Python
Python发送http请求解析返回json的实例
Mar 26 Python
python利用微信公众号实现报警功能
Jun 10 Python
Python面向对象程序设计之继承与多继承用法分析
Jul 13 Python
Python实现数据结构线性链表(单链表)算法示例
May 04 Python
Python学习笔记之pandas索引列、过滤、分组、求和功能示例
Jun 03 Python
python opencv摄像头的简单应用
Jun 06 Python
用Python实现最速下降法求极值的方法
Jul 10 Python
pyinstaller打包成无控制台程序时运行出错(与popen冲突的解决方法)
Apr 15 Python
python 使用建议与技巧分享(四)
Aug 18 Python
Python调用JavaScript代码的方法
Oct 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
将兴奋、喜悦和坎加斯带到戴安娜:亚马逊公主
2020/03/03 欧美动漫
浏览器预览PHP文件时顶部出现空白影响布局分析原因及解决办法
2013/01/11 PHP
浅谈php serialize()与unserialize()的用法
2013/06/05 PHP
PHP中常用的转义函数
2014/02/28 PHP
PHP获取数据库表中的数据插入新的表再原删除数据方法
2018/10/12 PHP
PHP+ajax实现上传、删除、修改单张图片及后台处理逻辑操作详解
2020/02/12 PHP
javascript之通用简单的table选项卡实现(二)
2010/05/09 Javascript
如何创建一个JavaScript弹出DIV窗口层的效果
2013/09/25 Javascript
Bootstrap弹出带合法性检查的登录框实例代码【推荐】
2016/06/23 Javascript
JS简单设置下拉选择框默认值的方法
2016/08/20 Javascript
老生常谈jquery id选择器和class选择器的区别
2017/02/12 Javascript
Scala解析Json字符串的实例详解
2017/10/11 Javascript
Vue.js 利用v-for中的index值实现隔行变色
2018/08/01 Javascript
使用jQuery给Table动态增加行、清空table的方法
2018/09/05 jQuery
webpack4之如何编写loader的方法步骤
2019/06/06 Javascript
bootstrap datepicker的基本使用教程
2019/07/09 Javascript
使用vue-router在Vue页面之间传递数据的方法
2019/07/15 Javascript
基于脚手架创建Vue项目实现步骤详解
2020/08/03 Javascript
python使用wmi模块获取windows下的系统信息 监控系统
2015/10/27 Python
用python的requests第三方模块抓取王者荣耀所有英雄的皮肤实例
2017/12/14 Python
python编程实现随机生成多个椭圆实例代码
2018/01/03 Python
Python用imghdr模块识别图片格式实例解析
2018/01/11 Python
Python判断对象是否为文件对象(file object)的三种方法示例
2019/04/26 Python
详解Python中的测试工具
2019/06/09 Python
Python read函数按字节(字符)读取文件的实现
2019/07/03 Python
Django框架表单操作实例分析
2019/11/04 Python
基于Python执行dos命令并获取输出的结果
2019/12/30 Python
如何基于matlab相机标定导出xml文件
2020/11/02 Python
轻松掌握CSS3中的字体大小单位rem的使用方法
2016/05/24 HTML / CSS
Canvas与Image互相转换示例代码
2013/08/09 HTML / CSS
微信浏览器取消缓存的方法
2015/03/28 HTML / CSS
领导干部贪图享乐整改措施
2014/09/21 职场文书
法院干警四风问题自我剖析材料
2014/09/29 职场文书
数学教师求职信范文
2015/03/20 职场文书
2015年度公共机构节能工作总结
2015/05/26 职场文书
篮球比赛通讯稿
2015/07/18 职场文书