生产者和消费者模型:
#!/usr/bin/env python #coding:utf8 import threading,Queue import time import random def producer(name,n):#生产者 # while True:#无限循环生产包子 time.sleep(random.randrange(3))#random生成一个3以内不包含3的随机数,通过随机数决定等待多长时间,主要便于测试 if q.qsize()<4:#判断队列个数如果小于4程序继续往下执行,#包子剩余的个数如果小于4个才生产包子,避免浪费.每个厨师在生产包子都会看还剩余几个 for i in range(2):#每个厨师生产2个包子上传到队列 print '%s生产了[%d]个包子 '%(name,n) q.put(n) q.join()#队列的个数为空则阻塞.#因为消费者每吃完一个包子都会告诉厨师,当所有包子都吃完厨师继续生产包子.#就是继续下一次循环 print '包子已卖光了,[%d]'%q.qsize() def consumer(name,n):#消费者 while True:#无限循环吃包子 print '%s 吃了[%d]个包子 '%(name,n) q.get()#吃掉一个包子从队列减1 time.sleep(1)#每个消费者吃掉一个包子的时候等待1秒 q.task_done()#每个消费者吃掉一个包子通知队列(厨师) if __name__=='__main__': q=Queue.Queue() c_name=['z1','z2','z3','z4']#4个消费者 p_name=['p1','p2']#2个厨师 for name in p_name: p=threading.Thread(target=producer,args=[name,1,])#开启2个线程调用producer函数,#2个厨师同时生产包子 p.start()#开启线程,线程的开关 for name in c_name: c=threading.Thread(target=consumer,args=[name,1,])#开启4个线程调用consumer函数,#4个消费者同时吃包子 c.start()#开启线程,线程的开关
执行结果:
p1生产了[1]个包子
p1生产了[1]个包子
z1 吃了[1]个包子
z4 吃了[1]个包子
z1 吃了[1]个包子
包子已卖光了,[0]
协程
协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。
协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:
协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。
协程的好处:
- 无需线程上下文切换的开销
- 无需原子操作锁定及同步的开销
- 方便切换控制流,简化编程模型
- 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。
缺点:
- 无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
- 进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序
使用yield实现协程操作例子
import time import queue def consumer(name): print("--->starting eating baozi...") while True: new_baozi = yield print("[%s] is eating baozi %s" % (name,new_baozi)) #time.sleep(1) def producer(): r = con.__next__() r = con2.__next__() n = 0 while n < 5: n +=1 con.send(n) con2.send(n) print("