zoukankan      html  css  js  c++  java
  • python之路(14)进程

    目录


     进程创建

      创建进程实现在python下的并发,同时调用多个cpu来操作线程

    方法一:

    from multiprocessing import Process
    import time
    
    
    def f(name):
        time.sleep(1)
        print('hello', name,time.ctime())
    
    if __name__ == '__main__':
        p_list=[]
        for i in range(3): #开启三个进程,此时是使用3个cpu,每个cpu分别执行一个
    
            p = Process(target=f, args=('alvin',))
            p_list.append(p)
            p.start()
    
        for i in p_list:
            i.join()
        print('end')  
    

    方法二:通过继承 

    from multiprocessing import Process
    import time
    
    class MyProcess(Process):
    
        # def __init__(self):
        #     super(MyProcess, self).__init__()
        #     #self.name = name
    
        def run(self):
            time.sleep(1)
            print ('hello', self.name,time.ctime()) #self.name是进程名
    
    
    if __name__ == '__main__':
        p_list=[]
    
    
        for i in range(3):
            p = MyProcess()
            # p.daemon=True #设置为守护进程
            p.start()
            p_list.append(p)
    
        for p in p_list:
            p.join() #如果子进程没有执行完,主进程就卡在这里,不往下运行
    
        print('end')
    
    #########################################
    hello MyProcess-1 Sat May  4 15:42:00 2019
    hello MyProcess-2 Sat May  4 15:42:00 2019
    hello MyProcess-3 Sat May  4 15:42:00 2019
    end
    

     os.getppid() 显示父进程的id

     os.getpid() 显示当前进程的id 

     p.is_alive() 实例方法,判断进程是否还活着 

     p.terminate() 直接停止进程运行

    进程间通信

      进程间通信与线程间通信不同,线程之间共享一块内存,简单的线程间通信只要设置全局变量或者同步对象event(具体看进程篇)就能做到。而进程在不同的两块内存之中。

    方案一:使用进程队列来实现进程间通信

    import time
    
    import multiprocessing
    def foo(q):
        time.sleep(1)
        print("son process",id(q))
        q.put(123) #在子进程中放入值
        q.put("chen")
    
    if __name__ == '__main__':
    
        q=multiprocessing.Queue() #创建进程队列
        p=multiprocessing.Process(target=foo,args=(q,)) #在进程之间传递进程队列,作为全局变量
        p.start()
    
        print("main process",id(q))
        print(q.get()) #在主进程中拿出数据
        print(q.get()) 

    方案二:使用双向管道来实现经常队列

    from multiprocessing import Process, Pipe
    def f(conn):
        conn.send([12, {"name":"chen"}, 'hello']) #子进程给主进程发送数据
        response=conn.recv() #子进程接收主进程发送的数据
        print("response",response)
        conn.close() #关闭管道
    
    
    if __name__ == '__main__':
    
        parent_conn, child_conn = Pipe() #创建双向管道
    
    
        p = Process(target=f, args=(child_conn,))
        p.start()
    
        print(parent_conn.recv())   # 主进程接收子进程发送的数据prints "[42, None, 'hello']"
        parent_conn.send("儿子你好!") #主进程给子进程发送数据
        p.join()
    

     方案二:使用Manager实现进程间通信

      Pipe和Queue只是实现了进程间数据的交互,并没有实现进程间数据共享,即一个进程修改另一个进程的数据

      Manager支持的类型有list,dict,Namespace,Lock,RLock,Semaphore,BoundedSemaphore,Condition,Event,Queue,Value和Array。

    from multiprocessing import Process, Manager
    
    def f(d, l,n):
        
        d[n] = '1'    #{0:"1"}
        d['2'] = 2    #{0:"1","2":2}
        l.append(n)   #[0,1,2,3,4,   0,1,2,3,4,5,6,7,8,9]
    
    if __name__ == '__main__':
    
        with Manager() as manager: #with语法自动close()
    
            d = manager.dict()#通过manager得到一个字典对象
            l = manager.list(range(5))#通过manager得到一个列表对象
    
            p_list = []
            for i in range(10):
                p = Process(target=f, args=(d,l,i)) #将通过manager创建的对象最为参数传入子进程中
                p.start()
                p_list.append(p)
    
            for res in p_list:
                res.join()
    
            print(d)
            print(l)

    注:进程间的通信是很耗费资源的,因为存在两块不同的内存之中,所以本质上是一个进程将数据拷贝到另一个进程,存在内存的消耗。

    进程同步(同步锁)和进程池

      在进程与进程之间的数据不共用,但是进程与进程间也有同时使用的系统资源,比如终端和屏幕,在多个进程向显示器输出内容的时候,可能会导致数据混乱的显现,比如:

     因此使用进程同步锁来规定同一时刻,只能有一个进程来使用共用资源。

    from multiprocessing import Process, Lock
    import time
    
    def f(lock, i):
        lock.acquire() #请求同步锁
        time.sleep(1)
        print('hello world ',i)
        lock.release() #释放同步锁
    
    if __name__ == '__main__':
        lock = Lock() #创建同步锁
    
        for num in range(10):
            Process(target=f, args=(lock, num)).start() 

    进程池 

      在内存中同时会有很多的进程需要执行,那改怎么去执行这些进程成了问题,如果去同时运行这些进程那就太耗费资源,但是一个一个执行就费时,因此引入进程池,使用一个折中 的办法,在进程池中指定最大执行进程数量,进程的完执行速度有快有慢,当进程池中的某个进程执行完,等待的进程就可以进入进程池执行,直到完成所有进程的执行。

    #每一秒执行5个进程
    from  multiprocessing import Pool
    import time
    
    def Foo(i):
    
        time.sleep(1)
        print(i)
    
        return "HELLO %s"%i
    
    def Bar(arg):
        print(arg)
        print("hello")
    
    if __name__ == '__main__':
    
        pool = Pool(5) #定义进程池的最大进程数。如果不指定数目,默认根据电脑的cpu数量
        for i in range(100): #开一百个子进程
            #开启进程池
            pool.apply_async(func=Foo, args=(i,),callback=Bar) #callback指定回调函数(就是某个动作或者函数执行成功后再去执行的函数)
    
        pool.close()
        pool.join()         # join与close调用顺序是固定的
    
  • 相关阅读:
    SSM中(Spring-SpringMVC-Mybatis)(一:概念)
    java中的==和equals()
    JAVA之二叉查找树
    Java中堆与栈
    java的运行机制(基础)
    覆盖(重写),重构,重载的区别
    JAVA多线程基础
    java中的类修饰符、成员变量修饰符、方法修饰符
    JAVA中的流程控制语句
    JAVA中的构造函数
  • 原文地址:https://www.cnblogs.com/shuzhixia/p/10829888.html
Copyright © 2011-2022 走看看