Pipe(管道),Event(事件),Semaphore(信号量),Pool(进程池),回调函数

一、关于Pipe(管道,队列就是基于管道),不常用,因为管道中的内容是共享的,数据不安全,而且一个数据取走后,其他人没法接收.

from multiprocessing import Process,Pipe
def f1(conn):
    from_zhujincheng = conn.recv()
    print('我是子进程')
    print('来自主进程的消息:',from_zhujincheng)
if __name__ == '__main__':
    conn1,conn2 = Pipe()  #创建一个管道对象,全双工,返回管道的两端,但是一端发送的消息,只能另外一端接收,自己这一端是不能接收的
    #可以将一端或者两端发送给其他的进程,那么多个进程之间就可以通过这一个管道进行通信了
    p1 = Process(target=f1,args=(conn2,))
    p1.start()
    conn1.send('小宝贝,你在哪')
    print('我是主进程')

二、关Event()  (简称事件)

e = Event()  #Event的状态默认为False

e.set() #将e的状态改为True

e.clear()  #将e的状态还原会False

e.wait()  #e的状态是False,程序就会阻塞在这里等待.

注意:Event一般只应用于2个进程间的通信,进程多了,无法成立改机制.

from multiprocessing import Process,Event
e = Event()  #创建事件对象,这个对象的初识状态为False
print('e的状态是:',e.is_set())
print('进程运行到这里了')
e.set()  #将e的状态改为True
print('e的状态是:',e.is_set())
e.clear()  #将e的状态改为False
e.wait()  #e这个事件对象如果值为False,就在我加wait的地方等待
print('进程过了wait')

三、关于multiprocessing中的Semaphore()方法(简称信号量)

Semaphore是一个内置的计数器,也是一把锁,可以设置同一时间段内,开锁的进程数,(出去一个进去一个),默认是1个进程

  跟Lock()函数相比,就是可以设置人数限制,同时执行某段代码

s = semphore(4)

s.acquire() #加锁

  需要锁住的代码

s.release() #解锁

from multiprocessing import Process,Semaphore
import time
import random
def f1(i,s):
    s.acquire()
    print("%s男士到了"%i)
    time.sleep(random.randint(1,3))
    s.release()
if __name__ == '__main__':
    s = Semaphore(2)  #锁,参数是同时可以开锁的进程数,此方法没有with 简便方法
    for i in range(4):
        P = Process(target=f1,args=(i,s))
        P.start()

四、关于进程池

from multiprocssing import Pool

Pool.map(obj,inter) #快速生成n项(可迭代项)任务,交给进程池,属于异步提交方式.参数1为开启进程的对象,参数2必须是可迭代的,把后面的可迭代对象给前面的进程代码执行,快速生成 n项(可迭代项)任务
Pool方法就是在一直开启着进程,每次执行任务时,就把任务放进进程池,(自带join方法:后面的任务必须等着前面的任务执行完才能进入).该池子的默认值数量为电脑cpu的个数;
这个跟多进程比较,就是节省创建和销毁进程的时间.
    #用多进程执行任务,慢在了,创建进程,和执行完任务后的销毁进程.而进程池,在池子里一直开着进程,执行完任务,但是不关进程通道.
使用进程池运算和创建进程运算,时间的对比
import
time from multiprocessing import Process,Pool def f1(n): for i in range(5): n = n+i if __name__ == '__main__': #使用进程池的执行代码所需时间 s_time = time.time() pool=Pool(4) #有100个任务,但是只有4个进程能执行. pool.map(f1,range(100)) #参数1为开启进程的对象,参数2必须是可迭代的,此map跟普通的map一样 e_time = time.time() dif_time = e_time - s_time #使用多进程执行代码所需的时间 p_s_t = time.time() #起始时间 p_list = [] for i in range(100): p = Process(target=f1,args=(i,)) p.start() p_list.append(p) [pp.join() for pp in p_list] p_e_t = time.time() p_dif_t = p_e_t - p_s_t print("进程池的时间:",dif_time) print("多进程的执行时间:",p_dif_t) #打印结果为:每次结果都不一致,但是进程池用比多进程用的时间短,是一定的. #进程池的时间: 0.1326451301574707 #多进程的执行时间: 2.274912118911743

进程池的同步提交方式

pool = Pool()

res = pool.apply(obj,args=(i,))  #同步执行任务,必须等任务执行结束才能给进程池提交下一个任务,可以直接拿到返回结果res

#进程池的同步异步方法
import time
from multiprocessing import Pool
def f1(n):
    time.sleep(0.5)
    return n*n
if __name__ == '__main__':
    pool = Pool(4)
    for i in range(10):
        res = pool.apply(f1,args=(i,)) #同步方法,就是把它该成串行,可以接收返回值
        print(res)

进程池的异步提交方式

pool.apply_async(obj,args(i,)) #异步提交

因为进程池比较特殊,主程序不会等待着进程池执行完毕才结束,但是主程序结束,进程池也就结束了,所以需要主进程等待进程池,

但是你无法判断是否还有其他任务提交给进程池,所以要冻结住进程池(poool.close()),然后再让主程序等待进程池(pool.join())

import time
from multiprocessing import Process,Pool
def f1(n):
    time.sleep(0.5)
    return n*n
if __name__ == '__main__':
    pool = Pool(4)
    res_list = []
    for i in range(10):
        res = pool.apply_async(f1,args=(i,))
        print(res) #任务瞬间提交出去,但是程序还没有计算出结果,这里打印的就是一堆结果对象(一堆内存地址)
        res_list.append(res)
    for i in res_list:
        print(i.get())
    print("主进程结束")
#解释:为什么打印出来的结果是有序的?
    # 因为放进列表里面的时候,是有顺序的,你get()的时候,用的列表里面的数据
    #  为什么结果是四个四个的出来?
    #  因为进程池的大小为4
需求:瞬间获取到所有进程执行完后的数据
import
time from multiprocessing import Pool def f1(n): time.sleep(0.5) return n*n if __name__ == '__main__': pool = Pool(4) res_list = [] #异步提交的方法 for i in range(10): res = pool.apply_async(f1,args=(i,)) print(res) #任务瞬间提交出去,但是程序还没有计算出结果,这里打印的就只是一堆还没有结果的,结果对象(一堆内存地址) res_list.append(res) #锁住进程池,不再让其他程序往里面扔新的任务,确保没有新的任务提交. pool.close() pool.join() for r in res_list: print(r.get()) time.sleep(2) #主进程运行结束,进程池里面的任务全部停止,不会等待进程池里面的任务 print("主进程结束")

五、回调函数

什么是回调函数:一个子进程执行完得到的返回值,扔给另一个进程去处理,这个过程叫回调,接收返回值进行处理的函数,叫做回调函数.

注意:回调函数是在主进程里面执行的.

import os
from multiprocessing import Pool,Process
def f1(n):
    print("参数值为",n)
    return n*n
def call_back_full(s):
    print("call进程id",os.getpid())
    print("回调函数的结果:",s)
if __name__ == '__main__':
    pool = Pool(4)
    res = pool.apply_async(f1,args=(5,),callback=call_back_full)  #callback 译为,回调
    pool.close()
    pool.join()
    print("主进程id",os.getpid())

 

猜你喜欢

转载自www.cnblogs.com/lgw1171435560/p/10251277.html
今日推荐