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()
    

      

  • 相关阅读:
    10. Regular Expression Matching
    9. Palindrome Number
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    4. Median of Two Sorted Arrays
    3. Longest Substring Without Repeating Characters
    2. Add Two Numbers
    链式表的按序号查找
    可持久化线段树——区间更新hdu4348
    主席树——树链上第k大spoj COT
  • 原文地址:https://www.cnblogs.com/asia-yang/p/10356157.html
Copyright © 2011-2022 走看看