zoukankan      html  css  js  c++  java
  • python学习笔记 day36 事件

    1. Event事件 ---标志,可以实现异步阻塞

    之前input,recv,accpet sleep等都是同步阻塞(写在哪个进程就会阻塞哪个),然后学了Lock锁 和信号量Semophore 都可以实现异步阻塞,同时阻塞多个进程(比如锁 只是同一时间只允许一个进程执行任务,所以比如开10个进程,就会同时异步阻塞九个)然后Semophore信号量可以允许多把钥匙,同一时间多个进程拿到钥匙执行任务,就会异步阻塞其他的进程(只能等着)

    现在Event 事件可以完成同时阻塞所有进程(相当于是一个标志,可以理解为交通信号灯,然后开的进程理解为车。交通信号灯,event为红(阻塞)进程,车就不能通过表现为阻塞,event 或交通灯为绿,车进程就可以通过,表现为非阻塞)

    from multiprocessing import Event
    e=Event()  # 实例化一个事件,默认阻塞(可以理解为交通信号灯,一开始红灯)
    e.set()  # 设置为非阻塞(交通灯变绿)
    e.wait()   # 默认为阻塞(红灯),set()之后变为非阻塞,(变绿)
    e.clear()   # 设置为阻塞(红灯),刚才的绿灯现在变为i红灯
    # e.wait()  # clear之后现在wait()就会一直阻塞

    运行结果:

    2. 使用事件模拟交通路口车辆通过:

    思路:

    首先实现一个traffic_light()函数,主要是完成交通灯红绿灯转换(三秒轮换),设置事件e的状态 阻塞和非阻塞每三秒转换;
    实现car() 完成车辆通过,会用到e的状态,阻塞,非阻塞,非阻塞时wait()直接就不等待,直接执行下面的代码,阻塞时就会一直等待,直到事件e变为非阻塞状态;

    在主进程中先开一个子进程,来执行交通灯转换,(由于是死循环,所以需要开一个子进程来完成,否则主进程会一直阻塞,无法执行下面的代码)

    然后开100个进程,模拟车,可以利用random模块和time模块设置并发,随机来多少辆车(根据i决定是否来,同时来的车辆i就是并发),然后执行car函数,是否立马通过,取决于e事件的是否阻塞状态,也就是是否为绿灯:

    代码实现:

    from multiprocessing import Process
    from multiprocessing import Event
    import random
    import time
    
    def traffic_light(e):
        """
        模拟交通灯,实际上是设置事件的阻塞状态,每三秒转换一次,代表红绿灯的转换
        :param e:
        :return:
        """
        while True:  # 死循环,红绿灯转换是需要一直工作的,事件e的阻塞状态一直在变(所以该函数需要单独要开一个子进程来实现,否则主进程会一直执行该死循环)
            if e.is_set():  # 查看事件e的阻塞状态,True代表非阻塞(绿灯)
                print("绿灯亮")
                time.sleep(3)  # 绿灯亮三秒
                e.clear()  # 设置为阻塞状态
            else:
                print("红灯亮")
                time.sleep(3)
                e.set()  # 红灯亮三秒后设置为绿灯(非阻塞)
    def car(i,e):
        """
        模拟车辆通过,车辆是否立马通过,取决于红绿灯的状态,也就是进程是否阻塞,取决于事件e的阻塞状态
        :param i:
        :param e:
        :return:
        """
        e.wait()   # 事件e阻塞时,这里会一直等待,直到事件set()也就是设置为非阻塞,才会执行下面的代码,不再等待
        print("%s车辆通过"%i)
    
    if __name__=="__main__":
        e=Event() # 实例化一个事件
        p=Process(target=traffic_light,args=(e,))   # 单独开一个子进程执行traffic_light()函数,因为该函数是个死循环,绝对不能在主进程中完成的
        p.start()
        for i in range(100):   # 创建100个进程(模拟100辆车)
            if i%random.randint(3,7)==0:  # 随机产生并发车辆的数目(有可能同时来3辆,有可能同时来5辆,都不确定)
                time.sleep(random.randint(1,3))  # 随机睡几秒(比如如果i是5 上面的随机数产生的刚好也是5 那么这个车辆就不会立马来,会先睡几秒,不会是并发的车辆)
            p=Process(target=car,args=(i,e))  # 并发的车辆(就是没有睡的)开启进程,但是是否立即通过取决于此时事件是否阻塞,如果阻塞就会等三秒,变为非阻塞,并发车辆才会同时通过
            p.start()

    运行结果:

    运行结果也是对的,,直观上好像红灯亮的时候车辆也过,但是(红灯亮的时候是不会立马有车辆通过,会等三秒才会有车辆通过的~) 

    或者直接把traffic_light()改成:

    运行结果:

    talk is cheap,show me the code
  • 相关阅读:
    Oracle实用SQL语句
    关键字过滤(转载)
    最简单的Cache
    .net中下载文件的方法(转载)
    为SharePoint 2013配置Office Web Apps
    使用Visual Studio 部署SharePoint时提示“路径中具有非法字符”
    TFS 2012 在IE 10(Windows 8)显示英文的解决方案
    为什么使用TFS 2012进行源代码管理——TFS 2012使用简介(一)
    SharePoint 2010 在WebPart页面上调用扩展方法报方法未定义的解决方案
    TreeView结合UpdatePanel使用时,SelectedNodeStyle不生效的解决方案
  • 原文地址:https://www.cnblogs.com/xuanxuanlove/p/9777159.html
Copyright © 2011-2022 走看看