Python中使用threading.Event协调线程的运行详解

作者:tinyid 时间:2023-08-05 04:39:05 

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服务启动的同时,看到工作线程里正在等待的情况。

来源:https://blog.csdn.net/cnweike/article/details/40821283

标签:Python,threading,Event,线程
0
投稿

猜你喜欢

  • Pytorch dataloader在加载最后一个batch时卡死的解决

    2022-09-15 06:50:34
  • python实现五子棋双人对弈

    2023-11-14 05:36:10
  • MySQL的查询计划中ken_len的值计算方法

    2024-01-24 13:32:49
  • javascript实现获取浏览器版本、操作系统类型

    2024-05-13 10:36:21
  • uni-app使用countdown插件实现倒计时

    2024-05-10 14:15:14
  • Python面向对象魔法方法和单例模块代码实例

    2023-05-02 19:03:16
  • 如何通过python检查文件是否被占用

    2023-03-20 12:25:00
  • python3连接MySQL8.0的两种方式

    2024-01-20 20:16:14
  • 使用 Angular 服务器端渲染 Transfer State Service

    2024-04-22 22:39:50
  • Python中Matplotlib的点、线形状、颜色以及绘制散点图

    2023-06-11 00:32:26
  • MySql安装启动两种方法教程详解

    2024-01-16 11:32:53
  • MySQL获得当前日期时间函数示例详解

    2024-01-27 07:54:48
  • 基于layer.js实现收货地址弹框选择然后返回相应的地址信息

    2024-05-08 09:32:22
  • 设计需知:移动网站设计应注意的技术细节

    2012-04-20 13:03:23
  • pytest中文文档之编写断言

    2023-05-05 04:11:34
  • python编写朴素贝叶斯用于文本分类

    2022-01-29 18:45:51
  • Python中变量交换的例子

    2021-04-02 13:28:36
  • [翻译]标记语言和样式手册 chapter 5 表单

    2008-01-23 17:20:00
  • mysql性能的检查和调优方法

    2009-05-17 09:21:00
  • Python检测端口IP字符串是否合法

    2023-09-03 11:51:26
  • asp之家 网络编程 m.aspxhome.com