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的web框架编写MVC配置来使其运行的教程
Apr 30 Python
python 转换 Javascript %u 字符串为python unicode的代码
Sep 06 Python
python 基础教程之Map使用方法
Jan 17 Python
100行Python代码实现自动抢火车票(附源码)
Jan 11 Python
Python获取指定字符前面的所有字符方法
May 02 Python
Python使用pymongo模块操作MongoDB的方法示例
Jul 20 Python
利用Python求阴影部分的面积实例代码
Dec 05 Python
如何利用Python分析出微信朋友男女统计图
Jan 25 Python
详解PyCharm安装MicroPython插件的教程
Jun 24 Python
python的re模块使用方法详解
Jul 26 Python
python3中sys.argv的实例用法
Apr 24 Python
如何把外网python虚拟环境迁移到内网
May 18 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实现文件下载代码分享
2014/08/19 PHP
php实现复制移动文件的方法
2015/07/29 PHP
Laravel SQL语句记录方式(推荐)
2016/05/26 PHP
利用php操作memcache缓存的基础方法示例
2017/08/02 PHP
PHP封装请求类实例分析【基于Yii框架】
2019/10/17 PHP
jquery 图片截取工具jquery.imagecropper.js
2010/04/09 Javascript
jquery Banner轮播选项卡
2016/12/26 Javascript
JavaScript函数基础详解
2017/02/03 Javascript
bootstrap jquery dataTable 异步ajax刷新表格数据的实现方法
2017/02/10 Javascript
vue深入解析之render function code详解
2017/07/18 Javascript
JavaScript从原型到原型链深入理解
2019/06/03 Javascript
Vue 设置axios请求格式为form-data的操作步骤
2019/10/29 Javascript
go和python调用其它程序并得到程序输出
2014/02/10 Python
python实现DNS正向查询、反向查询的例子
2014/04/25 Python
python使用Queue在多个子进程间交换数据的方法
2015/04/18 Python
python实现TCP服务器端与客户端的方法详解
2015/04/30 Python
Python的GUI框架PySide的安装配置教程
2016/02/16 Python
Python中二维列表如何获取子区域元素的组成
2017/01/19 Python
Python中read()、readline()和readlines()三者间的区别和用法
2017/07/30 Python
机器学习经典算法-logistic回归代码详解
2017/12/22 Python
Python内置模块logging用法实例分析
2018/02/12 Python
python3.X 抓取火车票信息【修正版】
2018/06/19 Python
python实现猜数字小游戏
2020/03/24 Python
Flask Web开发入门之文件上传(八)
2018/08/17 Python
python2.7实现邮件发送功能
2018/12/12 Python
python GUI库图形界面开发之PyQt5切换按钮控件QPushButton详细使用方法与实例
2020/02/28 Python
jupyter notebook的安装与使用详解
2020/05/18 Python
Python自带的IDE在哪里
2020/07/01 Python
Python异常处理机制结构实例解析
2020/07/23 Python
探索HTML5本地存储功能运用技巧
2016/03/02 HTML / CSS
巴西最大的家电和百货零售商:Casas Bahia
2016/11/22 全球购物
实习生自我鉴定范文
2013/12/05 职场文书
2014年消防工作总结
2014/11/21 职场文书
2015年四年级班主任工作总结
2015/10/22 职场文书
图文详解nginx日志切割的实现
2022/01/18 Servers
Python学习之时间包使用教程详解
2022/03/21 Python