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计算程序开始到程序结束的运行时间和程序运行的CPU时间
Nov 28 Python
Python程序员鲜为人知但你应该知道的17个问题
Jun 04 Python
Python greenlet实现原理和使用示例
Sep 24 Python
Python中内建函数的简单用法说明
May 05 Python
python删除服务器文件代码示例
Feb 09 Python
详解Python发送email的三种方式
Oct 18 Python
Python图像处理之颜色的定义与使用分析
Jan 03 Python
Python3最长回文子串算法示例
Mar 04 Python
Pyqt5 实现跳转界面并关闭当前界面的方法
Jun 19 Python
Python高并发解决方案实现过程详解
Jul 31 Python
利用Python判断整数是否是回文数的3种方法总结
Jul 07 Python
Python超详细分步解析随机漫步
Mar 17 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 fsockopen函数被禁用的解决办法
2013/08/07 PHP
php将一维数组转换为每3个连续值组成的二维数组
2016/05/06 PHP
PHP convert_uudecode()函数讲解
2019/02/14 PHP
接收键盘指令的脚本
2006/06/26 Javascript
统计jQuery中各字符串出现次数的工具
2012/05/03 Javascript
javascript延时加载之defer测试
2012/12/28 Javascript
如何编写高质量JS代码
2014/12/28 Javascript
全屏js头像上传插件源码高清版
2016/03/29 Javascript
jQuery事件绑定on()与弹窗实现代码
2016/04/28 Javascript
JS实现搜索框文字可删除功能
2016/12/28 Javascript
浅谈原生JS实现jQuery的animate()动画示例
2017/03/08 Javascript
基于vue-simplemde实现图片拖拽、粘贴功能
2018/04/12 Javascript
微信小程序按钮去除边框线分享页面功能
2018/08/27 Javascript
微信小程序实现星星评价效果
2018/11/02 Javascript
vscode中eslint插件的配置(prettier配置无效)
2019/09/10 Javascript
浅析Vue 防抖与节流的使用
2019/11/14 Javascript
基于JavaScript判断两个对象内容是否相等
2020/01/10 Javascript
使用Karma做vue组件单元测试的实现
2020/01/16 Javascript
小程序websocket心跳库(websocket-heartbeat-miniprogram)
2020/02/23 Javascript
好用的Python编辑器WingIDE的使用经验总结
2016/08/31 Python
Python 绘图和可视化详细介绍
2017/02/11 Python
Python实现中一次读取多个值的方法
2018/04/22 Python
python2 与 python3 实现共存的方法
2018/07/12 Python
使用Python获取并处理IP的类型及格式方法
2018/11/01 Python
简单几步用纯CSS3实现3D翻转效果
2019/01/17 HTML / CSS
香港卓悦化妆品官网:BONJOUR
2017/09/21 全球购物
Visual-Click葡萄牙:欧洲领先的在线眼镜商
2020/02/17 全球购物
期末考试动员演讲稿
2014/01/10 职场文书
制药工程专业个人求职自荐信
2014/01/25 职场文书
优秀毕业自我鉴定
2014/02/15 职场文书
优秀班主任事迹材料
2014/12/16 职场文书
趵突泉导游词
2015/02/03 职场文书
幼儿教师远程研修感悟
2015/11/18 职场文书
HTML页面滚动时部分内容位置固定不滚动的实现
2021/04/14 HTML / CSS
Vue详细的入门笔记
2021/05/10 Vue.js
解决IIS7下无法绑定https主机的问题
2022/04/29 Servers