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()方法会阻塞),所以当生产者开始执行的时候,这个消费者因为商品队列里有数据就被立即唤醒了。

最新文章

  1. ActiveMQ
  2. 读过的laravel文章
  3. jQuery DOM 与 原生DOM 互相转换的方法
  4. Jmeter—5 关联 响应数据传递-正则表达式提取器
  5. 获得View的真实高度
  6. poj 1985 Cow Marathon
  7. spring 中的两个DaoSupport类的使用对比
  8. iOS多线程的初步研究(七)-- dispatch对象
  9. 设计模式之 - 外观模式 (Facade design pattern)
  10. Asp.net Api中使用OAuth2.0实现“客户端验证”
  11. Python开发【内置模块篇】collections
  12. JavaScript Object中的函数assign
  13. git merge 和 git merge --no-ff的区别
  14. 二叉查找树(Binary Search Tree)
  15. 日期控件 DatePicker 在ie8不能用
  16. java.security.cert.CertificateException: No subject alternative names matching IP address xxx.xxx.xxx.xxx found
  17. HDU 6081 度度熊的王国战略(全局最小割Stoer-Wagner算法)
  18. 《modern-php》 - 阅读笔记 - 最佳实践
  19. springMVC学习记录1-使用XML进行配置
  20. 锐捷S2126交换机端口限速

热门文章

  1. 5W2H+35问
  2. npp 文本编辑器 开源
  3. Attach()和Detach()函数
  4. 微软新一代Surface发布,参数曝光
  5. poj3929
  6. android 三种定时器的写法
  7. ASP.NET实现头像剪切保存
  8. brctl命令
  9. .net framework 4.5 +steeltoe+ springcloud(三)实现Hystrix断路器
  10. Windows核心编程:第14章 探索虚拟内存