zoukankan      html  css  js  c++  java
  • Python学习---同步条件event/队列queue1223

    写在前面:

    在使用这些共享API的时候,我们要注意以下几点:

      在UNIX平台上,当某个进程终结之后,该进程需要被其父进程调用wait,否则进程成为僵尸进程(Zombie)。所以,有必要对每个Process对象调用join()方法 (实际上等同于wait)。对于多线程来说,由于只有一个进程,所以不存在此必要性。

      multiprocessing提供了threading包中没有的IPC(比如PipeQueue),效率上更高。应优先考虑PipeQueue,避免使用Lock/Event/Semaphore/Condition等同步方式 (因为它们占据的不是用户进程的资源)

      多进程应该避免共享资源。在多线程中,我们可以比较容易地共享资源,比如使用全局变量或者传递参数。在多进程情况下,由于每个进程有自己独立的内存空间,以上方法并不合适。此时我们可以通过共享内存和Manager的方法来共享资源。但这样做提高了程序的复杂度,并因为同步的需要而降低了程序的效率。

    Process.PID中保存有PID,如果进程还没有start(),则PIDNone

      window系统下,需要注意的是要想启动一个子进程,必须加上那句if __name__ == "main",进程相关的要写在这句下面。

    同步条件event

       条件同步和条件变量同步差不多意思,只是少了锁功能,因为条件同步设计于不访问共享资源的条件环境。

    围绕一个标志位来进行判断

    event=threading.Event():条件环境对象,初始值 为False;

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

    event.wait():如果 event.isSet()==False将阻塞线程;

    event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;

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

    案例一:

    import threading,time
    class Boss(threading.Thread):
        def run(self):
            print("BOSS:今晚大家都要加班到22:00。")
            event.isSet() or event.set()
            time.sleep(5)
            print("BOSS:<22:00>可以下班了。")
            event.isSet() or event.set()
    class Worker(threading.Thread):
        def run(self):
            event.wait()
            print("Worker:哎……命苦啊!")
            time.sleep(0.25)
            event.clear()
            event.wait()
            print("Worker:OhYeah!")
    if __name__=="__main__":
        event=threading.Event()
        threads=[]
        for i in range(5):
            threads.append(Worker())
        threads.append(Boss())
        for t in threads:
            t.start()
        for t in threads:
            t.join()

    案例二:

    import threading,time
    import random
    def light():
        if not event.isSet():
            event.set() #wait就不阻塞 #绿灯状态
        count = 0
        while True:
            if count < 10:
                print('33[42;1m--green light on---33[0m')
            elif count <13:
                print('33[43;1m--yellow light on---33[0m')
            elif count <20:
                if event.isSet():
                    event.clear()
                print('33[41;1m--red light on---33[0m')
            else:
                count = 0
                event.set() #打开绿灯
            time.sleep(1)
            count +=1
    def car(n):
        while 1:
            time.sleep(random.randrange(10))
            if  event.isSet(): #绿灯
                print("car [%s] is running.." % n)
            else:
                print("car [%s] is waiting for the red light.." %n)
    if __name__ == '__main__':
        event = threading.Event()
        Light = threading.Thread(target=light)
        Light.start()
        for i in range(3):
            t = threading.Thread(target=car,args=(i,))
            t.start()

    多线程利器---队列queue

    队列因为是可以使2遍都开口,所以FIFO,栈是开头封闭,只能从底部出,所以先进后出

    Python Queue模块有三种队列及构造函数:

    1、Python Queue模块的FIFO队列先进先出。   class queue.Queue(maxsize)

    2、LIFO类似于堆,即先进后出。              class queue.LifoQueue(maxsize)

    3、还有一种是优先级队列级别越低越先出来。   class queue.PriorityQueue(maxsize)

    注意:列表时线程不安全的,队列是安全的,内部有一把锁保证了我数据的安全

    import queue
    # 队列长度可为无限或者有限,默认是Queue(0),表示无限长
    d = queue.Queue(2)  #可通过Queue的构造函数的可选参数maxsize来设定队列长度,如果maxsize小于1就表示队列长度无限。
    d.put('hello', 0) # 第一个item为必需的,为插入项目的值;
                      # 第二个block为可选参数,默认为1。如果队列当前为空且block为1,线程阻塞,直到空出一个数据单元
                      # 如果block为0,put方法将引发Full异常。
    d.put('world', 0)
    # d.put('2017', 0) # 第三个,阻塞报异常
    print(d.get())    # get()方法从队头删除并返回一个项目。可选参数为block,默认为True。
                      # 如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。
                      # 如果队列为空且block为False,队列将引发Empty异常。
    print(d.get())

    image

    队列的方法

    此包中的常用方法(q = Queue.Queue()):
    q.qsize() 返回队列的大小
    q.empty() 如果队列为空,返回True,反之False
    q.full() 如果队列满了,返回True,反之False
    q.full 与 maxsize 大小对应
    q.get([block[, timeout]]) 获取队列,timeout等待时间
    q.get_nowait() 相当q.get(False)非阻塞 
    q.put(item) 写入队列,timeout等待时间
    q.put_nowait(item) 相当q.put(item, False)
    q.task_done() 在完成一项工作之后,
    q.task_done() 函数向任务已经完成的队列发送一个信号

    实例一:

    import threading,queue
    from time import sleep
    from random import randint
    class Production(threading.Thread):
        def run(self):
            while True:
                r=randint(0,100)
                q.put(r)
                print("生产出来%s号包子"%r)
                sleep(1)
    class Proces(threading.Thread):
        def run(self):
            while True:
                re=q.get()
                print("吃掉%s号包子"%re)
    if __name__=="__main__":
        q=queue.Queue(10)
        threads=[Production(),Production(),Production(),Proces()]
        for t in threads:
            t.start()

    image

    FTP作业

    更多参考

  • 相关阅读:
    AcWing 826. 单链表
    AcWing 803. 区间合并
    codeforces Codeforces Round #597 (Div. 2) D. Shichikuji and Power Grid
    球球大作战.exe
    RGB MIXER三原色混色器的制作
    125. 验证回文串
    110. 平衡二叉树
    112. 路径总和
    111. 二叉树的最小深度
    100. 相同的树
  • 原文地址:https://www.cnblogs.com/ftl1012/p/9384234.html
Copyright © 2011-2022 走看看