一、生产者消费者模型
 
  在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
 
  生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力,并且我可以根据生产速度和消费速度来均衡一下多少个生产者可以为多少个消费者提供足够的服务,就可以开多进程等等,而这些进程都是到阻塞队列或者说是缓冲区中去获取或者添加数据。
 
二、生产者消费者模型实现
 
  1、基于队列来实现一个生产者消费者模型

 from multiprocessing import Process,Queue
import time,random,os
def consumer(q):
while True:
res=q.get()
time.sleep(random.randint(1,3))
print('\033[45m%s 吃 %s\033[0m' %(os.getpid(),res)) def producer(q):
for i in range(10):
time.sleep(random.randint(1,3))
res='包子%s' %i
q.put(res)
print('\033[44m%s 生产了 %s\033[0m' %(os.getpid(),res)) if __name__ == '__main__':
q=Queue()
#生产者们:即厨师们
p1=Process(target=producer,args=(q,)) #消费者们:即吃货们
c1=Process(target=consumer,args=(q,)) #开始
p1.start()
c1.start()
print('主')

基于队列实现

  总结:

 #生产者消费者模型总结
#程序中有两类角色
一类负责生产数据(生产者)
一类负责处理数据(消费者) #引入生产者消费者模型为了解决的问题是:
平衡生产者与消费者之间的工作能力,从而提高程序整体处理数据的速度 #如何实现:
生产者<-->队列<——>消费者
#生产者消费者模型实现类程序的解耦和

  问题:

  通过上面基于队列的生产者消费者代码示例,我们发现一个问题:主进程永远不会结束,原因是:生产者p在生产完后就结束了,但是消费者c在取空了q之后,则一直处于死循环中且卡在q.get()这一步。解决方式无非是让生产者在生产完毕后,往队列中再发一个结束信号,这样消费者在接收到结束信号后就可以break出死循环

  2、主进程去发送一个结束信号
  注意:结束信号None,不一定要由生产者发,主进程里同样可以发,但主进程需要等生产者结束后才应该发送该信号

 from multiprocessing import Process, Queue
import time
def shenchan(q):
for i in range(10): # 每1秒生产一个包子
time.sleep(1)
print('生产%s号包子' % i)
q.put(i) # 生产一个放入队列(缓冲区) def xiaofei(q):
while 1:
time.sleep(0.5) # 一直从队列中拿包子,每0.5秒那一次
if q.get() == None: # 当从队列中拿时,拿到了None,就不拿了退出,None信号由主进程发出
break
else:
print('消费者吃%s号包子' % q.get()) # 消费者拿的比生产者产包子快,则队列中每包子,还get,等待消费者向队列中放包子再取 if __name__ == '__main__': q = Queue(10)
sc = Process(target=shenchan, args=(q,))
sc.start()
xf = Process(target=xiaofei, args=(q,))
xf.start()
sc.join() # 设join,阻塞一下,先让生产者,消费者进程执行完
q.put(None) # 再想队列中方None

发送信号解决

  3、通过JoinableQueue([maxsize]) 实现
   JoinableQueue([maxsize]):这就像是一个Queue对象,但队列允许项目的使用者通知生成者项目已经被成功处理。通知进程是使用共享的信号和条件变量来实现的。
  参数介绍:
    maxsize是队列中允许最大项数,省略则无大小限制。    
   方法介绍:
            JoinableQueue的实例p除了与Queue对象相同的方法之外还具有:
            q.task_done():使用者使用此方法发出信号,表示q.get()的返回项目已经被处理。如果调用此方法的次数大于从队列中删除项目的数量,将引发ValueError异常
            q.join():生产者调用此方法进行阻塞,直到队列中所有的项目均被处理。阻塞将持续到队列中的每个项目均调用q.task_done()方法为止,也就是队列中的数据全部被get拿走了。
 #生产者消费者模型
import time
from multiprocessing import Process,Queue,JoinableQueue def producer(q):
for i in range(1,11):
time.sleep(0.5)
print('生产了包子%s号' % i)
q.put(i)
q.join()
print('在这里等你')
def consumer(q):
while 1:
time.sleep(1)
s = q.get()
print('消费者吃了%s包子' % s)
q.task_done() #给q对象发送一个任务结束的信号 if __name__ == '__main__':
#通过队列来模拟缓冲区,大小设置为20
q = JoinableQueue(20)
#生产者进程
pro_p = Process(target=producer,args=(q,))
pro_p.start()
#消费者进程
con_p = Process(target=consumer,args=(q,))
con_p.daemon = True #
con_p.start()
pro_p.join()
print('主进程结束')

基于JoinableQueue

42_并发编程-JionableQueue的更多相关文章

  1. 并发编程,python的进程,与线程

    并发编程 操作系统发展史 基于单核研究 多道技术 1.空间上的复用 多个程序公用一套计算机硬件 2.时间上的复用 切换+保存状态 例子:洗衣 烧水 做饭 切换 1.程序遇到IO操作系统会立刻剥夺走CP ...

  2. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  3. 伪共享(false sharing),并发编程无声的性能杀手

    在并发编程过程中,我们大部分的焦点都放在如何控制共享变量的访问控制上(代码层面),但是很少人会关注系统硬件及 JVM 底层相关的影响因素.前段时间学习了一个牛X的高性能异步处理框架 Disruptor ...

  4. 【Java并发编程实战】----- AQS(四):CLH同步队列

    在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形.其主要从两方面进行了改造:节点的结构与节点等待机制.在结构上引入了头 ...

  5. 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport

    在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...

  6. 【Java并发编程实战】----- AQS(二):获取锁、释放锁

    上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...

  7. 【Java并发编程实战】-----“J.U.C”:CLH队列锁

    在前面介绍的几篇博客中总是提到CLH队列,在AQS中CLH队列是维护一组线程的严格按照FIFO的队列.他能够确保无饥饿,严格的先来先服务的公平性.下图是CLH队列节点的示意图: 在CLH队列的节点QN ...

  8. 【Java并发编程实战】-----“J.U.C”:Exchanger

    前面介绍了三个同步辅助类:CyclicBarrier.Barrier.Phaser,这篇博客介绍最后一个:Exchanger.JDK API是这样介绍的:可以在对中对元素进行配对和交换的线程的同步点. ...

  9. 【Java并发编程实战】-----“J.U.C”:CountDownlatch

    上篇博文([Java并发编程实战]-----"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一 ...

随机推荐

  1. leetcode543

    /** * Definition for a binary tree node. * public class TreeNode { * public int val; * public TreeNo ...

  2. mvn多环境下的配置

    在应用中,我们经常会遇到本地,测试和生产3种不同的环境,因此需要去配置不同的application. 定义resources: <resources> <resource> & ...

  3. 转 java的JsonObject对象提取值

    import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson ...

  4. http建立连接过程

    参考:http://blog.csdn.net/wangjun5159/article/details/51510594

  5. 自动滚动标签marquee

    <marquee>标签,它是成对出现的标签,首标签<marquee>和尾标签</marquee>之间的内容就是滚动内容.<marquee>标签的属性主要 ...

  6. R语言-线图(二)

      1.线图示例 plot()为高水平作图命令,axis().lines().legend()都为低水平作图命令 > rain<-read.csv("cityrain.csv&q ...

  7. 搭建React项目(一):在网页中使用

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. 【python原理解析】python中分片的实现原理及使用技巧

    首先:说明什么是序列? 序列中的每一个元素都会被分配一个序号,即元素的位置,也称为索引:在python中的序列包含:字符串.列表和元组 然后是:什么是分片? 分片就是通过操作索引访问及获得序列的一个或 ...

  9. 37 【kubernetes】搭建dashboard

    官方的操作步骤是:https://github.com/kubernetes/dashboard 我自己的步骤是: 1,下载yaml文件 wget https://raw.githubusercont ...

  10. java_19List 集合

    1List集合 有序的 collection(也称为序列).此接口的用户可以对列表中每个元素的插入位置进行精确地控制.用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素. 与 s ...