Python全栈学习笔记day 37:multiprocessing模块:(信号量 Semaphore、事件Event、进程间通信:队列Queue、生产者消费者模型JoinableQueue)

目录

一、信号量  multiprocess.Semaphore

二、事件 —— multiprocess.Event

三、进程间通信——队列

四、生产者消费者模型JoinableQueue


一、信号量  multiprocess.Semaphore

 意义:一套资源、代码同一时间只能被n个人访问、n个进程执行
格式:

from multiprocessing import Process
from multiprocessing import Semaphore

def ktv(i,sem):
    sem.acquire()            获取钥匙
    print('%s走进ktv'%i)
    print('%s走出ktv'%i)
    sem.release()            还钥匙


if __name__ == '__main__' :
    sem = Semaphore(4)       一共有几把钥匙
    for i in range(20):     
        p = Process(target=ktv,args=(i,sem))
        p.start()

二、事件 —— multiprocess.Event

事件:通过一个信号来控制多个进程同时执行或者阻塞,一个事件被创建之后,默认是阻塞状态,一个事件被创建之后,默认是阻塞状态

格式:

from multiprocessing import Event

e = Event()                   创建了一个事件
print(e.is_set())      False       查看一个事件的状态,默认被设置成阻塞
e.set()                       将这个事件的状态改为True
print(e.is_set())      True
e.wait()                      是依据e.is_set()的值来决定是否阻塞的
print(123456)
e.clear()                     将这个事件的状态改为False
print(e.is_set())      False
e.wait()                      等待(等待时为阻塞)事件的信号被变成True
print('*'*10)

红绿灯作业:

import time
import random
from multiprocessing import Event,Process
def cars(e,i):
    if not e.is_set():
        print('car%i在等待'%i)
        e.wait()    # 阻塞 直到得到一个 事件状态变成 True 的信号
    print('\033[0;32;40mcar%i通过\033[0m' % i)

def light(e):
    while True:
        if e.is_set():
            e.clear()
            print('\033[31m红灯亮了\033[0m')
        else:
            e.set()
            print('\033[32m绿灯亮了\033[0m')
        time.sleep(2)

if __name__ == '__main__':
    e = Event()
    traffic = Process(target=light,args=(e,))
    traffic.start()
    for i in range(20):
        car = Process(target=cars, args=(e,i))
        car.start()
        time.sleep(random.random())

三、进程间通信——队列

队列 先进先出,队列空了继续取q.get()数据会阻塞,队列满了继续存q.put()数据会阻塞

q.full()   # 队列是否满了返回True or False     不准确
from multiprocessing import Queue,Process
def produce(q):
    q.put('hello')

def consume(q):
    print(q.get())

if __name__ == '__main__':
    q = Queue()
    p = Process(target=produce,args=(q,))
    p.start()
    c = Process(target=consume, args=(q,))
    c.start()

 

四、生产者消费者模型JoinableQueue

get 、 task_done  连用。put 、join  连用

q.task_done() 
使用者使用此方法发出信号,表示q.get()返回的项目已经被处理。如果调用此方法的次数大于从队列中删除的项目数量,将引发ValueError异常。

q.join() 
生产者将使用此方法进行阻塞,直到队列中所有项目均被处理。阻塞将持续到为队列中的每个项目均调用q.task_done()方法为止。

import time
import random
from multiprocessing import Process,JoinableQueue
def consumer(q,name):
    while True:
        food = q.get()
        print('\033[31m%s消费了%s\033[0m' % (name,food))
        time.sleep(random.randint(1,3))
        q.task_done()     # count - 1

def producer(name,food,q):
    for i in range(4):
        time.sleep(random.randint(1,3))
        f = '%s生产了%s%s'%(name,food,i)
        print(f)
        q.put(f)
    q.join()    # 阻塞  直到一个队列中的所有数据 全部被处理完毕

if __name__  == '__main__':
    q = JoinableQueue(20)
    p1 = Process(target=producer,args=('Egon','包子',q))
    p2 = Process(target=producer, args=('wusir','泔水', q))
    c1 = Process(target=consumer, args=(q,'alex'))
    c2 = Process(target=consumer, args=(q,'jinboss'))
    p1.start()
    p2.start()
    c1.daemon = True   # 设置为守护进程 主进程中的代码执行完毕之后,子进程自动结束
    c2.daemon = True
    c1.start()
    c2.start()
    p1.join()
    p2.join()      # 感知一个进程的结束

代码解释:

#  在消费者这一端:
    # 每次获取一个数据
    # 处理一个数据
    # 发送一个记号 : 标志一个数据被处理成功

# 在生产者这一端:
    # 每一次生产一个数据,
    # 且每一次生产的数据都放在队列中
    # 在队列中刻上一个记号
    # 当生产者全部生产完毕之后,
    # join信号 : 已经停止生产数据了
                # 且要等待之前被刻上的记号都被消费完
                # 当数据都被处理完时,join阻塞结束

代码过程:

consumer 中把所有的任务消耗完
producer 端 的 join感知到,停止阻塞
所有的producer进程结束
主进程中的p.join结束
主进程中代码结束
守护进程(消费者的进程)结束

猜你喜欢

转载自blog.csdn.net/qq_35883464/article/details/85112762