Python多任务编程思想(二)

       本文继续Python多任务编程思想(一)的话题,讨论python中进程的剩余几个概念:守护进程、重写Process类创建子进程以及进程池技术。

一.守护进程

       主进程创建守护进程:①设置daemon属性为true;②虽然进程间是相互独立的,守护进程会在主进程"代码执行结束"时终止;③守护进程中不能再创建子进程。

        守护进程与守护线程存在很大差异,在学习完守护线程后,将对二者做出总结区分。

代码示例:

'''p1为守护进程,在主进程退出时,p1结束循环;p2为非守护进程,不会受到主进程的影响'''
from multiprocessing import Process
import time
import os
import signal

def foo():
    while True:
        print(time.ctime())
        time.sleep(3)

def bar():
    print("非守护进程启动")
    time.sleep(10)
    print("非守护进程结束")


p1=Process(target=foo)
p2=Process(target=bar)

#避免守护进程成为僵尸进程
signal.signal(signal.SIGCHLD, signal.SIG_IGN)

if __name__ == '__main__':
    p1.daemon=True
    p1.start()
    p2.start()
    print("守护进程:",p1.pid)
    print("非守护进程:",p2.pid)
    time.sleep(4)
    print("主进程{}结束!".format(os.getpid()))

二.创建自己的进程类:
    1.继承Process类
    2.重写__init__ 方法,并且调用父类的__init__
    3.重写run方法:生成对象后调用start方法,自动运行run

'''创建自己的进程类
    ①继承Process类
    ②重写__init__ 并且调用父类的__init__
    ③重写run方法,此时生成对象后调用start就会自动运行run
'''
from multiprocessing import Process
import time

class ClockProcess(Process):
    def __init__(self, value):
        # 调用父类的__init__方法
        super().__init__()
        self.value = value

    def run(self):
        '''重写run方法,子进程启动后,自动执行此方法'''
        for i in range(3):
            time.sleep(self.value)
            print(time.ctime())


# 创建子进程
p1 = ClockProcess(2)
p1.start()
p1.join()

三.进程池技术

       背景:多进程编程能并行执行多个任务,具有效率高,创建方便,运行独立,不受其他进程影响,数据安全等特点;但进程的创建和删除都需要消耗计算机的资源。如果有大量任务需要多进程完成,且可能需要频繁地创建和删除进程,将给计算机带来大量的资源消耗。
       原理:在进程池内运行一定数量的进程,通过这些进程完成进程池队列中的事件,直到事件执行完,减少进程的不断地创建删除过程。
       实现:
             ①创建进程池,在进程池中放入适当进程
             ②将事件加入到进程池队列
             ③事件不断运行,直到所有事件运行完毕
             ④关闭进程池,回收进程

           from multiprocessing import Pool

           pool = Pool(processes)        #创建进程池对象;参数:表示进程池中有多少进程

           pool.apply_async(func, args, kwds)       #将事件放入进程池队列
                  参数:func 要执行的事件,args 给func用元组传参,kwds 给func用字典传参
                  返回值:返回事件对象 通过get()方法获取事件函数返回值

           pool.map(func,iter)       #将要完成的事件放入进程池
                  参数:func 要完成的事件函数,iter 可迭代对象给func传值
                  返回值:时间函数的返回值列表

           pool.close()       #关闭进程池,不能再添加新的事件

           pool.join()       #阻塞等待回收进程池

        方法一:apply_async

'''方式一:使用"apply_async()"需要自己创建列表,维护返回值'''
from multiprocessing import Pool
from time import sleep,ctime

def event(message):
    sleep(2)
    print(ctime(),':',message)
    return '&' + str(message) + '&'

print(ctime())
pool = Pool(4)
r_list = []

for i in range(10):
    # apply效率非常低,进程池中同一时刻,只有一个进程在运行。程序在此处阻塞
    # element = pool.apply(event,(i,))
    # apply_async可以提升效率:进程池中的进程并行执行,一起返回,直到所有进程都执行完毕;
    # 程序在此处并不会阻塞
    element = pool.apply_async(event,(i,))
    print(element)
    r_list.append(element)

for e in r_list:
    # print(e)
    # apply_async返回事件对象,可通过get()方法获取事件函数返回值
    print(e.get())

print(ctime())

pool.close()
pool.join()

方法二.  map

'''方法二 使用进程池的map方法;返回值为列表,无需自己创建维护列表'''
from multiprocessing import Pool
from time import sleep,ctime

def event(message):
    sleep(1)
    print(ctime(),':',message)
    return '&' + str(message) + '&'

pool = Pool(4)

print(ctime())
# 阻塞,返回值为列表
l = pool.map(event, range(10))
# 非阻塞,返回值为对象,使用get()方法获取列表,get()会阻塞
# l = pool.map_async(event, range(10))

print(l)
# print(l.get())

pool.close()
pool.join()

print(ctime())

 

你可能感兴趣的:(Python处理并发)