day9-event(红绿灯例子)
背景
在日常生活中经常遇到红绿灯,我们就很好理解红绿灯的例子,就是红灯停,绿灯行。
概述
我现在生成一个线程,这个线程我让它扮演红绿灯,它每过一段时间就变成绿灯,一会儿又变成红灯。然后我再生成3-5个线程作为车。车看见红灯,它就停下来等着,如果说是绿灯,车子就走。所以就涉及到红绿灯这个线程,红绿灯的这个线程就跟车线程之前产生了依赖关系了。就是红绿灯这个线程必须在绿灯的时候才能走,在红灯的时候就立刻停下来。所以他们之间,一个线程会根据另外一个线程的状态产生一些变化。类似这种场景的实现,就引出了一个新的知识点:event,即事件。
就是我们红绿灯这个线程每隔30秒,由绿灯变成红灯,然后红灯会持续20秒,也就是每一次的状态切换,就是一次事件的发生。然后它切换了一次灯的状态。其他的车就会根据这个状态做不同的动作,这个就是因为一个事件导致其他事件的连锁变化。
事件(event)
用法
Python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法wait、clear、set
事件的处理机制
全局定义一个"Flag",如果"Flag"值为False,那么当程序执行event.wait方法时就会阻塞,如果"Flag"值为True,那么event.wait方法时便不再阻塞。
- clear #将"Flag"设置为False
- set #将"Flag"设置为True
event = threading.event() #设置一个事件的全局变量
event.is_set() #判断是否已经设置标志位
#客户端线程等待标志位被设定
event.wait() #没有设置标志位的时候会阻塞,一遇到标志位就不再阻塞
#服务器端线程能够设置或清除
event.set() #设置标志位
event.clear() #清除标志位
如果标志位被设置了,代表绿灯,直接通行。
如果标志位被清除,代表红灯,wait等待变绿灯。
多个线程可以等待相同的事件。
红绿灯例子
说明:通过Event来实现两个或多个线程间的交互,下面的例子,即起动一个线程做交通指挥灯,生成几个线程做车辆,车辆行驶按红灯停,绿灯行的规则。
import threading, time event = threading.Event() # 设置一个事件的全局变量 def lighter(): "红绿灯" count = 0 event.set() # 先设置绿灯 while True: if count > 5 and count < 10: # 改成红灯 event.clear() # 清除标志位 print("\033[41mred light is on ....\033[0m") elif count > 10: event.set() # 设置标志位,变绿灯 count = 0 else: print("\033[42mgree light is on ....\033[0m") time.sleep(1) count += 1 def car(name): "车子" while True: #判断是否已经设置标志位 if event.is_set(): # 有标志位,代表是绿灯 print("[%s] running ...."%name) time.sleep(1) else: # 代表红灯 print("[%s] sees red light ,waiting ...."%name) event.wait() # 阻塞(没有标志位的时候阻塞,有标志位的时候不阻塞) print("\033[34;1mgreen light is on , [%s] start going ...\033[0m"%name) light = threading.Thread(target=lighter, ) light.start() car1 = threading.Thread(target=car, args=("AUDI",)) car1.start() car2 = threading.Thread(target=car, args=("ChangChen",)) car2.start() #运行输出
员工进公司刷卡例子
说明:员工进公司门要刷卡, 我们这里设置一个线程是“门”, 再设置几个线程为“员工”,员工看到门没打开,就刷卡,刷完卡,门开了,员工就可以通过。
#_*_coding:utf-8_*_ import threading import time import random def door(): door_open_time_counter = 0 while True: if door_swiping_event.is_set(): print("\033[32;1mdoor opening....\033[0m") door_open_time_counter +=1 else: print("\033[31;1mdoor closed...., swipe to open.\033[0m") door_open_time_counter = 0 #清空计时器 door_swiping_event.wait() if door_open_time_counter > 3:#门开了已经3s了,该关了 door_swiping_event.clear() time.sleep(0.5) def staff(n): print("staff [%s] is comming..." % n ) while True: if door_swiping_event.is_set(): print("\033[34;1mdoor is opened, passing.....\033[0m") break else: print("staff [%s] sees door got closed, swipping the card....." % n) print(door_swiping_event.set()) door_swiping_event.set() print("after set ",door_swiping_event.set()) time.sleep(0.5) door_swiping_event = threading.Event() #设置事件 door_thread = threading.Thread(target=door) door_thread.start() for i in range(5): p = threading.Thread(target=staff,args=(i,)) time.sleep(random.randrange(3)) p.start() #运行输出