03:进程Queue --- 生产者消费者模型

1 进程Queue介绍

 

 

 

1 进程间数据隔离,两个进程进行通信,借助于Queue

2 进程间通信:IPC
-借助于Queue实现进程间通信
   -借助于文件
   
   -借助于数据库
   -借助于消息队列:rabbitmq,kafka....

1.1 基本使用


from multiprocessing import Process,Queue
​
​
if __name__ == '__main__':
    # maxsize表示Queue的大小是多少,能放多少东西
    queue=Queue(3)
    ## 放数据
    queue.put('zhangsan')
    queue.put('liss')
    queue.put('wwwww')
​
    queue.put('wwwww',timeout=0.1)
​
    # queue.put_nowait('sdafsd')
    #
    # res=queue.get()
    # print(res)
    # res=queue.get()
    # print(res)
    res=queue.get()
    # print(res)
    # # 卡住
    # # res=queue.get()
    # res=queue.get_nowait()
    # print(res)
    
    
    
  '''
  # 实例化得到一个对象,数字表示queue的大小(默认不传参,可以当成无限大,但其实有最大值)
  queue=Queue(3)
  # 放值
  # block:是否阻塞
  #timeout:等待的时间
  queue.put()
  #取值
  # block:是否阻塞
  #timeout:等待的时间
  queue.get()
  
  # 不等待,如果满了,就报错
  queue.put_nowait()
  
  # 去取值,如果没有值,直接报错
  res=queue.get_nowait()
  
  #查看这个queue是否满
  queue.full()
  #查看queue是否是空的
  queue.empty()
  
  # 查看queue中有几个值
  queue.qsize()
  '''

 

 

2 通过Queue实现进程间通信

 

 

 


from multiprocessing import Process,Queue
​
​
import os
import time
​
def task(queue):
    print('我这个进程%s开始放数据了'%os.getpid())
    time.sleep(10)
    queue.put('lqz is handsome')
    print('%s我放完了' % os.getpid())
​
​
if __name__ == '__main__':
    #不写数字,表示可以任意长度
    queue=Queue()
    p=Process(target=task,args=[queue,])
    p.start()
​
    res=queue.get()  #会卡在这
    print(res)

 

 

3 批量生产数据放入Queue再批量取出

 

 


from multiprocessing import Process,Queue
import os
​
def get_task(queue):
    res=queue.get()
    print('%s这个进程取了数据:%s'%(os.getpid(),res))
​
​
def put_task(queue):
    queue.put('%s:放了数据'%os.getpid())
​
if __name__ == '__main__':
    queue=Queue(1)
    p1=Process(target=put_task,args=[queue])
    p2=Process(target=put_task,args=[queue])
    p1.start()
    p2.start()
​
​
    p3=Process(target=get_task,args=[queue])
    p4=Process(target=get_task,args=[queue])
    p3.start()
    p4.start()

 





4 生产者消费者模型(重点)

 

 

 

from multiprocessing import Process, Queue
# import os
#
# import time
# import random
# def producer(queue):
#     # 生产的东西,放到Queue中
#     for i in range(10):
#         data = '%s这个厨师,整了第%s个包子' % (os.getpid(), i)
#         print(data)
#         # 模拟一下延迟
#         time.sleep(random.randint(1,3))
#         queue.put('第%s个包子'%i)
#
#
# def consumer(queue):
#     # 消费者从queue中取数据,消费(吃包子)
#     while True:
#
#         res=queue.get()
#         # 模拟一下延迟
#         time.sleep(random.randint(1, 3))
#         print('%s这个消费者,吃了%s'%(os.getpid(),res))
#
#
#
# if __name__ == '__main__':
#     queue=Queue(3)
#     p=Process(target=producer,args=[queue,])
#     p.start()
#
#     p1=Process(target=consumer,args=[queue,])
#     p1.start()
​
​
###### 改良(生产者以及不生产东西了,但是消费者还在等着拿)
# import os
#
# import time
# import random
# def producer(queue):
#     # 生产的东西,放到Queue中
#     for i in range(10):
#         data = '%s这个厨师,整了第%s个包子' % (os.getpid(), i)
#         print(data)
#         # 模拟一下延迟
#         time.sleep(random.randint(1,3))
#         queue.put('第%s个包子'%i)
#     # 生产完了,在queue中放一个None
#     queue.put(None)
#
#
# def consumer(queue):
#     # 消费者从queue中取数据,消费(吃包子)
#     while True:
#
#         res=queue.get()
#         if not res:break # 如果去到空,说明打烊了(生产者不生产了),退出
#         # 模拟一下延迟
#         time.sleep(random.randint(1, 3))
#         print('%s这个消费者,吃了%s'%(os.getpid(),res))
#
#
#
# if __name__ == '__main__':
#     queue=Queue(3)
#     p=Process(target=producer,args=[queue,])
#     p.start()
#
#     p1=Process(target=consumer,args=[queue,])
#     p1.start()
​
​
#### 把put none 放在主进程中执行
import os
​
# import time
# import random
# def producer(queue):
#     # 生产的东西,放到Queue中
#     for i in range(10):
#         data = '%s这个厨师,整了第%s个包子' % (os.getpid(), i)
#         print(data)
#         # 模拟一下延迟
#         time.sleep(random.randint(1,3))
#         queue.put('第%s个包子'%i)
#
#
#
# def consumer(queue):
#     # 消费者从queue中取数据,消费(吃包子)
#     while True:
#
#         res=queue.get()
#         if not res:break # 如果去到空,说明打烊了(生产者不生产了),退出
#         # 模拟一下延迟
#         time.sleep(random.randint(1, 3))
#         print('%s这个消费者,吃了%s'%(os.getpid(),res))
#
#
#
# if __name__ == '__main__':
#     queue=Queue(3)
#     p=Process(target=producer,args=[queue,])
#     p.start()
#
#     p1=Process(target=consumer,args=[queue,])
#     p1.start()
#
#     # 如果把put None放在这,会有问题
#     # 主进程会先执行这句话,消费进程读到None,直接结束,生产者进程没有结束,于是生产一直在生产,消费已经不消费了
#     # 直到Queue满了,就一直卡在这了
#     # queue.put(None)
#
#     ### 现在就要放在这,你把问题解决
#     p.join()
#     queue.put(None)

 



5 多个生产者多个消费者的生产者消费者模型

 

 

 

# 多个生产者在生产,多个消费者在消费
# import time
# import random
# def producer(queue,food):
#     # 生产的东西,放到Queue中
#     for i in range(10):
#         data = '%s这个厨师,做了第%s个%s' % (os.getpid(), i,food)
#         print(data)
#         # 模拟一下延迟
#         time.sleep(random.randint(1,3))
#         queue.put('第%s个%s'%(i,food))
#
#
# def consumer(queue):
#     # 消费者从queue中取数据,消费(吃包子)
#     while True:
#         res=queue.get()
#         if not res:break # 如果去到空,说明打烊了(生产者不生产了),退出
#         # 模拟一下延迟
#         time.sleep(random.randint(1, 3))
#         print('%s这个消费者,吃了%s'%(os.getpid(),res))
#
#
#
# if __name__ == '__main__':
#     queue=Queue(3)
#     ##起了三个生产者
#     p1=Process(target=producer,args=[queue,'包子'])
#     p2=Process(target=producer,args=[queue,'骨头'])
#     p3=Process(target=producer,args=[queue,'泔水'])
#     p1.start()
#     p2.start()
#     p3.start()
#
#
#
#     # 起了两个消费者
#     c1=Process(target=consumer,args=[queue,])
#     c2=Process(target=consumer,args=[queue,])
#     c1.start()
#     c2.start()
#
#     ##等三个生产者都生产完,放三个None
#     p1.join()
#     p2.join()
#     p3.join()
#     queue.put(None)
#     queue.put(None)
#     queue.put(None)
##如果消费者多,比生产者多出来的消费者不会停
import time
import random
​
​
def producer(queue, food,name):
    # 生产的东西,放到Queue中
    for i in range(10):
        data = '%s:这个厨师,做了第%s个%s' % (name, i, food)
        print(data)
        # 模拟一下延迟
        time.sleep(random.randint(1, 3))
        queue.put('第%s个%s' % (i, food))
​
​
def consumer(queue,name):
    # 消费者从queue中取数据,消费(吃包子)
    while True:
        try:
            res = queue.get(timeout=20)
            # 模拟一下延迟
            time.sleep(random.randint(1, 3))
            print('%s这个消费者,吃了%s' % (name, res))
        except Exception as e:
            print(e)
            break
​
​
if __name__ == '__main__':
    queue = Queue(3)
    ##起了三个生产者
    p1 = Process(target=producer, args=[queue, '包子','egon'])
    p2 = Process(target=producer, args=[queue, '骨头','lqz'])
    p3 = Process(target=producer, args=[queue, '泔水','jsason'])
    p1.start()
    p2.start()
    p3.start()
​
    # 起了两个消费者
    c1 = Process(target=consumer, args=[queue, '孟良'])
    c2 = Process(target=consumer, args=[queue,'池劲涛' ])
    c3 = Process(target=consumer, args=[queue,'池劲涛' ])
    c4 = Process(target=consumer, args=[queue,'池劲涛' ])
    c1.start()
    c2.start()
    c3.start()
    c4.start()

 

6 进程间数据共享(了解)

 

 

 


from multiprocessing import Process,Manager,Lock
​
# 魔法方法:类内以__开头__结尾的方法,都叫魔法方法,某种情况下会触发它的执行
'''
__init__ :类()触发
__new__:
__getattr__
__setattr__
__getitem__
__setitem__
​
'''# def task(dic,lock):
#     # lock.acquire()
#     # dic['count']-=1
#     # lock.release()
#     with lock:
#         dic['count'] -= 1
#
# if __name__ == '__main__':
#     lock = Lock()
#     with Manager() as m:
#         # 如果直接定义dict,这个dict在多个进程中其实是多份,进程如果改,只改了自己的
#         #如果定义的是m.dict({'count': 100}),多个进程之间就可以共享这个数据
#         dic = m.dict({'count': 100})
#
#         p_l = []
#         for i in range(100):
#             p = Process(target=task, args=(dic, lock))
#             p_l.append(p)
#             p.start()
#         for p in p_l:
#             p.join()
​
​
​
​
​
def task(dic,lock):
    with lock:
        dic['count'] -= 1if __name__ == '__main__':
    lock = Lock()
    dic={'count':100}
    p_l = []
    for i in range(100):
        p = Process(target=task, args=(dic, lock))
        p_l.append(p)
        p.start()
    for p in p_l:
        p.join()
​
​
​
    print(dic)
​

 


7 线程概念

 

 

 

如果把我们上课的过程看成一个进程的话,那么我们要做的是耳朵听老师讲课,手上还要记笔记,脑子还要思考问题,这样才能高效的完成听课的任务。而如果只提供进程这个机制的话,上面这三件事将不能同时执行,同一时间只能做一件事,听的时候就不能记笔记,也不能用脑子思考,这是其一;如果老师在黑板上写演算过程,我们开始记笔记,而老师突然有一步推不下去了,阻塞住了,他在那边思考着,而我们呢,也不能干其他事,即使你想趁此时思考一下刚才没听懂的一个问题都不行,这是其二


#进程是资源分配的最小单位,线程是CPU调度的最小单位。每一个进程中至少有一个线程。
​
​
from threading import Thread
from queue import Queue
import os
import time


def task():
    time.sleep(3)
    print('我是子线程执行的')
    print(os.getpid())


if __name__ == '__main__':
    # 启动线程

    ctime = time.time()
    t = Thread(target=task)
    t.start()
    # task()
    time.sleep(3)
    print(os.getpid())
    print(time.time() - ctime)

 

 

 

总结

1 Queue:进程间通信
    -实例化得到一个对象
    -对象.put()
    -对象.get()
    
2 生产者消费者模型
3 通过共享变量来共享数据(进程间数据是隔离的)
	-Manager实现多个进程操作同一个变量
    -加锁
4 线程,每个进程下最少有一个线程,cup调度的最小单位
5 python如何开启线程



posted @ 2021-04-23 20:28  Jerry`  阅读(59)  评论(0编辑  收藏  举报