Queue与Pool

Queue(消息队列)

1.创建消息队列

import multiprocessing
q = multiprocessing.Queue(队列长度)

2.Queue相关方法

  • put 往队列放数据 ,队列已经满的时候,则会进入等待状态,等队列取出数据后再次放入数据。
  • put_nowait 往队列放数据,当队列已经满的时候,不等待直接报错
  • get 取出数据,当队列已经没有数据的时候则进入等待状态,直到有数据的时候再将数据取出。
  • get_nowait 取出数据,队列中没有数据可以取出的时候,直接报错。(在判断队列是否为空的时候,可能会出现已经放入数据却判断为空的情况,这是因为放入数据的操作和判断是否为空的操作是同时进行的,所以出现这种情况
  • qsize 队列长度
  • empty 判断队列是否为空
  • full 判断队列是否已满
  • q.put()#放数据
    q.full()#判断是否为空
    q.empty()#判断队列是否为空
    ...

3.Queue实现进程间的通信

    进程间的通信可以通过socket、文件、Queue来实现。这里重点说一下Queue实现进程间的通信。

队列的特性为先进先出,它是内存里的一块内存,当一个进程向队列中写入任务时,另一个进程就可以从队列中读取任务。

这样在程序在运行的时候读取任务和执行任务就不必互相等待,解决了其强耦合问题。

def download_from_web(q):
    """
    下载数据
    模拟从网上下载的数据
    :return:
    """
    data=[11,22,33,44]
    #向队列中写入数据
    for temp in data:
        q.put(temp)
    print("下载器已经下载完并且存到队列中")
def analysis_data(q):
    """
    数据处理
    :return:
    """
    #从队列中获取数据
    waitting_analysis_data=list()
    while True:
        data=q.get()
        waitting_analysis_data.append(data)
        if q.empty():
            break
    print(waitting_analysis_data)

if __name__ == '__main__':
    # 1.创建一个队列
    q = multiprocessing.Queue(3)
    p1 = multiprocessing.Process(target=download_from_web, args=(q,))
    p2 = multiprocessing.Process(target=analysis_data, args=(q,))
    p1.start()
    p2.start()

结果:

Queue与Pool_第1张图片


Pool(进程池)

当需要创建的子进程数量不多的时候,可以直接利用multiprocess中的Process动态生成多个进程,但如果是成千上百个目标,则需要手动创建,那工作量便大大增加。这时我们可以使用multiprocess模块实现创建进程池,来提高效率。

1.初始化Pool

from multiprocess import Pool
po=Pool(3)  #初始化一个进程池,限定其最大进程数为3

初始化进程池,规定最大进程数后,当有新的请求提交到进程池时,如果进程池没有满的时候,就会创建一个新的进程来执行该请求,但是如果池中的进程已经达到最大的限定值,那么该请求就会等待,直到进程池中的任务有结束的时候才会用之前的进程来执行新的任务。

2.进程池的相关方法

  • apply()   以同步方式来添加进程
  • apply_async()  以异步的方式来添加进程
  • close()  关闭进程池,不接受新的任务。但是仍然可以使用
  • terminate() 不管任务是否完成,立即终止

join()主进程阻塞,等待子进程完成后再结束。必须写在close()和terminal()之后。

3.进程池之间的通信

import multiprocessing
q=multiprocessing.Manager().Queue() #创建一个队列

队列数据的写入方式同上面介绍的Queue的方法相同。

4.案例

from  multiprocessing import Pool,Manager
import os,time,random

def worker(q):
    t_start=time.time()
    while True:
        print('%s开始执行'%q.get())
        #random.random()随机生成0-1之间的浮点数
        # time.sleep(random.random()*2)
        time.sleep(1)
        if q.empty()==True:
            break
        print("******")
    t_stop=time.time()
    print('执行完毕,耗时%f'%(t_stop-t_start))
if __name__ == '__main__':
    po=Pool(3)
    #定义一个进程池,最大进程数3
    q=Manager().Queue()
    for i in range(0,10):
        q.put(i)
        #Pool().apply_async(要调用的目标,(传递给目标的参数元组))
        #每次循环将会用空闲出来的子进程去调用目标
    # res=po.apply_async(worker,(q,))#执行完毕,耗时10.004573

    res1=po.apply(worker, (q,)) #执行完毕,耗时10.010573
    print("------start--------")
    po.close()#关闭进程池
    po.join()#等到po中所有子进程执行完成,必须放在close之后。
    print("--------end----------")
#进程池重复利用进程池里的进程去执行任务。

总结:同步方式执行即依次执行,异步执行方式为并发执行。

你可能感兴趣的:(Queue与Pool)