Python多线程-Event(事件对象)
程序员文章站
2022-03-07 16:57:37
Event 事件对象管理一个内部标志,通过 方法将其设置为 ,并使用 方法将其设置为 。`wait() True False`。 方法: is_set() 当且仅当内部标志为 时返回 。 set() 将内部标志设置为 。所有等待它成为 的线程都被唤醒。当标志保持在 的状态时,线程调用 是不会阻塞的。 ......
event
事件对象管理一个内部标志,通过set()
方法将其设置为true
,并使用clear()
方法将其设置为false
。wait()
方法阻塞,直到标志为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()方法会阻塞),所以当生产者开始执行的时候,这个消费者因为商品队列里有数据就被立即唤醒了。
上一篇: 前端——基础