zoukankan      html  css  js  c++  java
  • Python多线程-Event(事件对象)

    Event

    事件对象管理一个内部标志,通过set()方法将其设置为True,并使用clear()方法将其设置为Falsewait()方法阻塞,直到标志为True。该标志初始为False

    方法:
    is_set()
    当且仅当内部标志为True时返回True

    set()
    将内部标志设置为True。所有等待它成为True的线程都被唤醒。当标志保持在True的状态时,线程调用wait()是不会阻塞的。

    clear()
    将内部标志重置为False。随后,调用wait()的线程将阻塞,直到另一个线程调用set()将内部标志重新设置为True

    wait(timeout=None)
    阻塞直到内部标志为真。如果内部标志在wait()方法调用时为True,则立即返回。否则,则阻塞,直到另一个线程调用set()将标志设置为True,或发生超时。
    该方法总是返回True,除非设置了timeout并发生超时。

    生产者与消费之--Event版

    # -*- coding:utf-8 -*-
    import threading
    import time
    import queue
    
    
    event = threading.Event()
    goods = queue.Queue(5)
    num = 0
    
    
    class Producer(threading.Thread):
        def run(self):
            global num
            while True:
                if goods.empty():
                    event.clear()
                    for _ in range(5):
                        goods.put('商品-' + str(num))
                        print('生产了商品-{0}.'.format(str(num)))
                        num += 1
                        time.sleep(1)
                    event.set()
    
    
    class Customer(threading.Thread):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.money = 7
    
        def run(self):
            while self.money:
                event.wait()
                self.money -= 1
                print('{0} 买了一个{1}.'.format(
                    threading.current_thread().name, goods.get()))
                time.sleep(1)
            print('{0}没钱了,回家.'.format(threading.current_thread().name))
    
    
    if __name__ == '__main__':
        p = Producer(daemon=True)
        c1 = Customer(name='Alice')
        c2 = Customer(name='Bob')
        c2.start()
        p.start()
        c1.start()
        c1.join()
        c2.join()
    

    运行结果:

    生产了商品-0.
    生产了商品-1.
    生产了商品-2.
    生产了商品-3.
    生产了商品-4.
    Alice 买了一个商品-0.
    Bob 买了一个商品-1.
    Alice 买了一个商品-2.
    Bob 买了一个商品-3.
    Alice 买了一个商品-4.
    生产了商品-5.
    生产了商品-6.
    生产了商品-7.
    生产了商品-8.
    生产了商品-9.
    Alice 买了一个商品-5.
    Bob 买了一个商品-6.
    Alice 买了一个商品-7.
    Bob 买了一个商品-8.
    生产了商品-10.
    Alice 买了一个商品-9.
    生产了商品-11.
    生产了商品-12.
    生产了商品-13.
    生产了商品-14.
    Alice 买了一个商品-10.
    Bob 买了一个商品-11.
    Alice没钱了,回家.
    Bob 买了一个商品-12.
    Bob 买了一个商品-13.
    Bob没钱了,回家.
    

    这里会出现一种特殊情况,当消费者线程较多时会大量出现:

    生产了商品-0.
    生产了商品-1.
    生产了商品-2.
    生产了商品-3.
    生产了商品-4.
    Bob 买了一个商品-0.
    Alice 买了一个商品-1.
    Bob 买了一个商品-2.
    Alice 买了一个商品-3.
    Bob 买了一个商品-4.
    生产了商品-5.					# !!!!!
    Alice 买了一个商品-5.			    # !!!!!
    生产了商品-6.
    生产了商品-7.
    生产了商品-8.
    生产了商品-9.
    Bob 买了一个商品-6.
    Alice 买了一个商品-7.
    Alice 买了一个商品-8.
    Bob 买了一个商品-9.
    生产了商品-10.
    生产了商品-11.
    生产了商品-12.
    生产了商品-13.
    生产了商品-14.
    Alice 买了一个商品-10.
    Bob 买了一个商品-11.
    Bob 买了一个商品-12.
    Alice 买了一个商品-13.
    Bob没钱了,回家.
    Alice没钱了,回家.
    

    这是因为生产者在轮询检查商品是否为空会有很小的延迟,在这个延迟中有消费者线程正好跑过了wait()方法,而阻塞在了商品获取这里(商品使用了队列,队列是线程安全的,当队列为空时,get()方法会阻塞),所以当生产者开始执行的时候,这个消费者因为商品队列里有数据就被立即唤醒了。

  • 相关阅读:
    12 go实现几中基本排序算法
    5 控制语句
    9 函数
    4. 常量与运算符
    AI
    AI
    AI
    AI
    ML
    ML
  • 原文地址:https://www.cnblogs.com/thunderLL/p/9861465.html
Copyright © 2011-2022 走看看