千家信息网

11.python并发入门(part5 event对象)

发表于:2024-10-02 作者:千家信息网编辑
千家信息网最后更新 2024年10月02日,一、引入event。每个线程,都是一个独立运行的个体,并且每个线程的运行状态是无法预测的。如果一个程序中有很多个线程,程序的其他线程需要判断某个线程的运行状态,来确定自己下一步要执行哪些操作。thre
千家信息网最后更新 2024年10月02日11.python并发入门(part5 event对象)

一、引入event。

每个线程,都是一个独立运行的个体,并且每个线程的运行状态是无法预测的。

如果一个程序中有很多个线程,程序的其他线程需要判断某个线程的运行状态,来确定自己下一步要执行哪些操作。

threading模块中的event对象恰好能做到这一点,event对象包含了一个可以通过线程设置的一个信号标志位,它允许线程一直等待某些事件的发生。

在初始化默认的情况下,event对象中的信号标识被设置为"假",如果这时,有一个线程等待这个event对象,而这个event对象的信号标志为"假",那么这个线程就会被一直阻塞下去,直到这个event信号标志为"真",所有等待这个event对象的线程才会被唤醒。

也就是说,一个线程如果等待的event对象中的信号标志位"真",这个线程会忽略这个事件(event),继续执行。


二、event对象的常用方法。

event.isSet():返回event的状态值。

event.wait(): 当event对象内部的信号标识设置为"假"(False),所有等待这个event对象的线程将会全部被阻塞。


event.set():设置event对象内部的信号标识为"真"(True),所有等待这个event对象的线程将会被唤醒,等待操作系统的调度。


event.clear():恢复event的状态值为False。


下面这个图,能让你清楚的明白event.wait和event.set之间的关系:


三、event使用示例。

我们来考虑下event对象的应用场景。

假如,在一个程序中,有多个线程需要到redis中来取数据,每个线程都要去尝试着去连接redis服务器,一般情况下,redis如果连接不成功,在所有线程中都需要尝试着去重新连接。

如果我们想要在程序启动时,先要确保redis服务器工作正常,接着在让其他工作的线程去连接redis服务器,当遇到这种需求的时候,使用event对象就是一个非常不错的选择。

我们可以使用event机制去让各个工作的线程去做一个简单的通信,主线程去连接redis服务器,如果连接到了,event对象内的信号标识改为真,其余工作的线程就会被唤醒。


示例:

#!/usr/local/bin/python2.7

# -*- coding:utf-8 -*-

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)

def main():

redis_ready = threading.Event()

t1 = threading.Thread(target=worker,args=(redis_ready,),name="threading-1")

t1.start()

t2 = threading.Thread(target=worker,args=(redis_ready,),name="threading-2")

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)

redis_ready.set()

if __name__ == '__main__':

main()


输出结果:

(threading-1) waiting for redis ready....

(threading-2) waiting for redis ready....

(MainThread) first of all,check redis server, make sure it is ok , and then trigger the redis ready event

(threading-1) redis ready,and connect to redis server and do some work Sun May 14 09:35:46 2017

(threading-2) redis ready,and connect to redis server and do some work Sun May 14 09:35:46 2017


代码分析:

在上面这段代码中,一共开了三个线程,分别是threading-1和threading-2还有主线程,首先主线程运行了main()函数,产生了一个event对象,这个event对象信号的初始值是False,然后创建了threading-1和threading-2两个线程并且运行,输出一条日志first of all,check redis server, make sure it is ok , and then trigger the redis ready event后sleep 3秒,此时切换到了threading-1,threading-1首先执行了worker函数,输出一次日志,然后执行event.wait方法,当这个event对象的信号标识为False时,threading-1就被阻塞住了,暂时无法执行woker函数后面的内容,当threading-1被阻塞住后,随即切换到threading-2(为什么一定切换到threading-2呢?这是因为主线程还在sleep),threading-2此时也去执行woker函数,同样先输出一条日志waiting for redis ready....,当执行到event.wait时,这个event对象的信号标志位依旧为False,所以执行到这里的时候,threading-2也会被阻塞。

过了3秒后,MainThread主线程sleep结束,开始向下运行,执行了redis_ready.set()后,我们创建的那个名为redis_ready的event对象中的信号标志会变为True,当这event对象的信号标志变为True之后,之前阻塞的threading-1和threading-2都会被唤醒,继续执行woker函数后面的代码。

(threading-1) redis ready,and connect to redis server and do some work Sun May 14 09:35:46 2017

(threading-2) redis ready,and connect to redis server and do some work Sun May 14 09:35:46 2017


四、event对象的补充。

threading.Event的wait方法还接受一个超时参数,默认情况下如果事件一致没有发生,wait方法会一直阻塞下去,而加入这个超时参数之后,如果阻塞时间超过这个参数设定的值之后,wait方法会返回。对应于上面的应用场景,如果Redis服务器一致没有启动,我们希望子线程能够打印一些日志来不断地提醒我们当前没有一个可以连接的Redis服务,我们就可以通过设置这个超时参数来达成这样的目的:


def worker(event):

while not event.is_set():

logging.debug('Waiting for redis ready...')

event.wait(2)

logging.debug('redis ready, and connect to redis server and do some work [%s]', time.ctime())

time.sleep(1)


线程 对象 信号 阻塞 标志 服务 运行 函数 方法 服务器 标识 参数 日志 状态 程序 工作 输出 事件 代码 情况 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 云服务器供应商如何注册 数据库的安全保护措施主要有 光传输网络技术考试答案 嵌入式软件开发在哪培训 99gan无法连接服务器 mysql 服务器字符集 网络安全委员会第三次会议讲话 安徽软件开发应用 数据库中最低成绩 软件开发风险管理主要目标 幼儿园网络安全管理规章制度 南京网络技术支持服务 亚马逊互联网科技有限公司 物流软件开发要注意哪几个方面 火山抖音服务器几点升级完毕 计算机网络安全技术王群 怎么查看服务器是不是物理机器 宁波市思文互联网科技有限公司 软件开发应用研究现状 尚游网络技术上海 sql数据库事务并发量 nosql数据库怎么设置 护苗网络安全手抄报模板 佛山金通软件开发有限公司 网络安全结构图 数据库批是啥 软件开发人员职业分析和小结 用户如何提高数据库性能 河南哪里学计算机网络技术 阿里adb数据库语法1726
0