第十章:使用进程、线程和协程提供并发性-multiprocessing:像线程一样管理进程-向进程传递消息

10.4.10 向进程传递消息
类似于线程,对于多个进程,一种常见的使用模式是将一个工作划分到多个工作进程中并行地运行。要想有效地使用多个进程,通常要求它们之间有某种通信,这样才能分解工作,并完成结果的聚集。利用multiprocessing完成进程间通信的一种简单方法是使用一个Queue来回传递消息。能够用pickle串行化的任何对象都可以通过Queue传递。

import multiprocessing


class MyFancyClass:

    def __init__(self,name):
        self.name = name

    def do_something(self):
        proc_name = multiprocessing.current_process().name
        print('Doing something fancy in {} for {}!'.format(
            proc_name,self.name))

def worker(q):
    obj = q.get()
    obj.do_something()


if __name__ == '__main__':
    queue = multiprocessing.Queue()

    p = multiprocessing.Process(target=worker,args=(queue,))
    p.start()

    queue.put(MyFancyClass('Fancy Dan'))

    # Wait for the worker to finish.
    queue.close()
    queue.join_thread()
    p.join()

这个例子只是向一个工作进程传递已给消息,然后主进程等待这个工作进程完成。
运行结果:
在这里插入图片描述
来看一个更复杂的例子,这里展示了如何管理多个工作进程,它们都消费一个JoinableQueue的数据,并把结果传递会父进程。这里使用“毒药”技术来停止工作进程。建立具体任务后,主程序会在作业队列中为每个工作进程增加一个“stop”值。当一个工作进程遇到这个特定值时,就会退出其处理循环。主进程使用任务队列的join()方法等待所有任务都完成后才开始处理结果。

import multiprocessing
import time


class Consumer(multiprocessing.Process):

    def __init__(self,task_queue,result_queue):
        multiprocessing.Process.__init__(self)
        self.task_queue = task_queue
        self.result_queue = result_queue

    def run(self):
        proc_name = self.name
        while True:
            next_task = self.task_queue.get()
            if next_task is None:
                # Poison pill means shutdown.
                print('{}:Exiting'.format(proc_name))
                self.task_queue.task_done()
                break
            print('{}:{}'.format(proc_name,next_task))
            answer = next_task()
            self.task_queue.task_done()
            self.result_queue.put(answer)


class Task:
    
    def __init__(self,a,b):
        self.a = a
        self.b = b

    def __call__(self):
        time.sleep(0.1) # Pretend to take time to do the work.
        return '{self.a} * {self.b} = {product}'.format(
            self=self,product=self.a * self.b)

    def __str__(self):
        return '{self.a} * {self.b}'.format(self=self)


if __name__ == '__main__':
    # Establish communication queues.
    tasks = multiprocessing.JoinableQueue()
    results = multiprocessing.Queue()

    # Start consumers.
    num_consumers = multiprocessing.cpu_count() * 2
    print('Creating {} consumers'.format(num_consumers))
    consumers = [
        Consumer(tasks,results)
        for i in range(num_consumers)
        ]
    for w in consumers:
        w.start()
    # Enqueue jobs.
    num_jobs = 10
    for i in range(num_jobs):
        tasks.put(Task(i,i))

    # Add a poison pill for each consumer.
    for i in range(num_consumers):
        tasks.put(None)

    # Wait for all of the tasks to finish.
    tasks.join()

    # Start printing results.
    while num_jobs:
        result = results.get()
        print('Result:',result)
        num_jobs -= 1

尽管作业按顺序进入队列,但它们的执行却是并行的,所以不能保证它们完成的顺序。
运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值