zoukankan      html  css  js  c++  java
  • (三十二)管道,事件,信号量,进程池

    一、管道---Pipe

    这是一个单向流动的管道,一次产生一对。看代码:

    from multiprocessing import Pipe,Process
    def f(c):
        print(c.recv())#接收不需要表明个数
    if __name__ == '__main__':
        conn1, conn2 = Pipe()#一次产生两个通道
        p = Process(target=f, args=(conn2,))
        p.start()
        conn1.send('哈哈哈哈哈akfnaslknf')#发送不需要使用字节流
    
    看看源码:
    def Pipe(duplex=True):#duplex:有两部分的
        return Connection(), Connection()#这里返回了两个
    

      

    二、事件--Event

    def f(e):
        print('hello,Python!!')
        e.set()#把状态修改为True,如果不修改,程序会停不下来
    if __name__ == '__main__':
        ev = Event()#初始状态是False
        print(ev.is_set())#查看事件当前的状态
        p = Process(target=f, args=(ev,))
        p.start()
        # ev.clear()#设置事件状态为False
    

      

    三、信号量---Semaphore

    先看代码吧:

    import random

    From fultiprocessing import Process,Semaphore
    def f(s):
        s.acquire()#这里会-1
        # time.sleep(2)#(1)
        time.sleep(random.randint(1, 5))#(2)
        print('hello')
        s.release()#这里会+1

    if __name__ == '__main__':
        s = Semaphore(4)#设置一个数量
        for i in range(10):
            p = Process(target=f, args=(s,))
            p.start()

    说明一下:信号量就像是创建了4个通道,进去一个进程会把们锁上,别人来了没有钥匙进不去,只有等某个进程完成了,其他的进程才可以进来。

    所以,使用(1)处的方式打印出来时,就是四个一组的被打印出来,而使用(2)处的方式打印时,就有点随机了。这是因为,每次随机出来的时间不一样,所以等待的时间也不一样,某个进程完成后其他的就可以抢夺这个通道。

    四、进程池---Pool

    1. map()
     def f(n):
        time.sleep(1)
        print(n)
    if __name__ == '__main__':
        po = Pool(4)
        po.map(f, range(10))#使用方式类似前面的方式,第一个参数是函数名,第二个是可迭代的参数
    

      

    使用线程池,做操作比直接使用进程,要节省时间,看下代码:

    # def fn(n):
    #     for i in range(5):
    #         n += i
    #
    # if __name__ == '__main__':
    #     st = time.time()
    #     po = Pool(os.cpu_count())
    #     po.map(fn, range(100))
    #     et = time.time()
    #
    #
    #     pst = time.time()
    #     lst = []
    #     for i in range(100):
    #         p = Process(target=fn, args=(i,))
    #         p.start()
    #         lst.append(p)
    #     [pro.join() for pro in lst]
    #     pet = time.time()
    #     print(et - st)
    #     print(pet-pst)
    

      2.进程池---apply()

    def f(n):
        # print(n*n)
        return n*n
    if __name__ == '__main__':
        po = Pool(4)
        for i in range(10):
            res = po.apply(f, args=(i,))#还可以接收返回值
            print(res)
    

      

    这个执行顺序是同步的,那么和下面的代码有什么区别吗?

    def f(n):
        pass
    for i in range(10):
        p = Process(target=f,args=(i,))
        p.start()
    

      

    上面两段代码都是串行,但是还是有很大区别的:(1)使用进程池,其实只是创建了4个进程,而且这四个进程是一直被复用的,直到任务完成才销毁,而下面这种却创建了10个进程。(2

     3.进程池---apply_async()

      看代码:

    def f(n):
        # print(n)
        time.sleep(1)
        return n**2
    if __name__ == '__main__':
        po = Pool(4)
        res_lst = []#收集结果集
        for i in range(10):
            res = po.apply_async(f, args=(i,))#也可以接收返回值,但是接收到的是结果对象,不是直接的值。
            #res.get()#这个get()与队列Queue的get()类似,不拿到值,誓不罢休,所以就会等着进程处理完返回了值后再继续往下走,
            # 但是这样循环就没有意义了。所以把这个结果集收集起来,然后在统一处理。
            res_lst.append(res)
        #集中处理结果集
        for r in res_lst:
            print(r.get())
        #使用close()为的是锁住进程池,不让别的程序继续往这个进程池丢任务,这样做完自己的任务后就可以结束了。
        po.close()#锁住进程池
        po.join()#等待所有任务被执行完,不然主进程结束,子进程也跟着结束了
    

     4.进程池---apply_async(),回调函数

    看代码:

    def f(i):
        return i**2
    def callBackFunc(n):
        print(n)
    if __name__ == '__main__':
        po = Pool(4)
        for i in range(10):
    	#callback=callBackFunc这里就是一个函数名
            po.apply_async(f, args=(i,), callback=callBackFunc)
        po.close()
        po.join()
    

      

  • 相关阅读:
    计算机网络通信
    javap查看class文件
    JDK动态代理与CGLib动态代理
    error the @annotation pointcut expression is only supported at Java 5 compliance
    redis清空缓存
    利用HttpURLConnection发送请求
    linux下用命令导出mysql表数据
    adb push和pull使用
    mysqld.exe占比cpu 100% 解决方案
    养成好习惯
  • 原文地址:https://www.cnblogs.com/asia-yang/p/10356157.html
Copyright © 2011-2022 走看看