zoukankan      html  css  js  c++  java
  • 多进程

    多进程

    1. 进程创建的两种方式 multiprocessing

    # 第一种方式
    from multiprocessing import Process
    import time
    
    def task(name):
        print(f'{name} is running')
        time.sleep(2)
        print(f'{name} is gone')
    
    if __name__ == '__main__':   # 在Windows环境下,必须在main下开启子进程
        p = Process(target=task, args=('meet',))   # args元组形式   创建一个进程对象
        p.start()
        print("===主进程")
    
    """
    结果:
    ===主进程
    meet is running
    meet is done
    """
    
    # p.start():开启子进程的命令,通知操作系统在内存中开辟一个进程空间,将主进程的数据copy加载到子进程空间中,然后操作系统调用cpu去执行子进程。    开销较大,因此会先执行主进程的代码。
    
    # 第二种方式
    from multiprocessing import Process
    import time
    
    class MyProcess(Process):
        
        def __init__(self, name):
            super().__init__()		# 重构父类的方法
            self.name = name
        def run(self):			# 必须写run()
            print(f'{self.name} is running')
            time.sleep(2)
            print(f"{self.name} is gone")
    
    if __name__ == '__main__':
        p = MyProcess('meet')	# 默认执行run()
        p.start()		# 开启子进程的命令
        print("===主进程")
    
    

    2. 进程pid (process id)

    进程在内存中的唯一标识。

    终端命令: tasklist # 查看计算机当前所有进程的pid

    终端命令: tasklist|findstr pycharm # 查看pycharm的pid

    代码 :

    import os
    print(os.getpid())		# 查看当前进程的pid
    
    print(os.getppid())		# 查看父进程的pid
    

    3. 验证进程之间的空间隔离

    from multiprocessing import Process
    
    lst = [1, 2]
    def task():
        lst.append(3)
        print(f'子进程的:{lst}')
    
    if __name__ == '__main__':
        p = Process(target=task)
        p.start()
        print(f'主进程的:{lst}')
    """
    主进程的:[1, 2]
    子进程的:[1, 2, 3]
    """
    # 主进程与子进程之间存在空间隔离。
    

    4. 进程对象join方法

    join :让主进程等待子进程结束之后,再执行主进程。(让主进程阻塞) 
    
    from multiprocessing import Process
    import time
    
    def task(sec):
        print('is running')
        time.sleep(sec)
        print('is gone')
    
    if __name__ == '__main__':
        start_time = time.time()
    
        p1 = Process(target=task, args=(1,))
        p2 = Process(target=task, args=(2,))
        p3 = Process(target=task, args=(3,))
        p1.start()
        p2.start()
        p3.start()
    # 同时开启
        p1.join()
        print(f'p1时间:{time.time()-start_time}')  # 1s多
        p2.join()
        print(f'p2时间:{time.time()-start_time}')	 # 2s多
        p3.join()
        print(f'p3时间:{time.time()-start_time}')  # 3s多
    
    
    from multiprocessing import Process
    import time
    
    def task(sec):
        print('is running')
        time.sleep(sec)
        print('is gone')
    
    if __name__ == '__main__':
        start_time = time.time()
    
        p1 = Process(target=task, args=(3,))
        p2 = Process(target=task, args=(2,))
        p3 = Process(target=task, args=(1,))  # 改变时间
        p1.start()
        p2.start()
        p3.start()
    # 同时开启
        p1.join()
        print(f'p1时间:{time.time()-start_time}')  # 3s多  #阻塞
        p2.join()
        print(f'p2时间:{time.time()-start_time}')	 # 3s多
        p3.join()
        print(f'p3时间:{time.time()-start_time}')  # 3s多
    
    # 面试题:将下面代码优化
    from multiprocessing import Process
    import time
    
    def task(sec):
        print('is running')
        time.sleep(sec)
        print('is gone')
    
    if __name__ == '__main__':
        start_time = time.time()
    
        p1 = Process(target=task, args=(1,))
        p2 = Process(target=task, args=(2,))
        p3 = Process(target=task, args=(3,))
        p1.start()
        p2.start()
        p3.start()
    
        p1.join()
        p2.join()
        p3.join()
        print(f'运行时间:{time.time()-start_time}')  # 3s多
        
    # 上面代码优化:
        lst = []
        for i in range(1,4):
            p = Process(target=task, args=(i,))
            lst.append(p)
            p.start()
    
        for i in lst:
            i.join()
        print(f'运行时间:{time.time()-start_time}')
        
    # 错误的优化:
    	for i in range(1,4)
           p = Process(target=task, args=(i,))
           p.start()
           p.join()
        print(f'运行时间:{time.time()-start_time}')
    

    5. 进程对象其他属性

    p.terminate()		# 结束子进程(杀死)
    
    p.is_alive()		# 判断子进程是否活着 True/False
    
    p = Process(target=task, args=('meet',), age=18)	# 给子进程对象添加一个age属性。
    print(p.age)	# 18
    

    6. 僵尸进程与孤儿进程

    6.1 僵尸进程

    实际中,主进程只有等待子进程结束后,主进程才结束。

    基于Unix环境(linux,macOS):

    主进程时刻监测子进程的运行状态,当子进程结束后,一段时间内,才会将子进程回收。

    为什么不马上回收?

    1. 主进程与子进程是异步关系,主进程无法马上获取子进程是什么时候结束;
    2. 如果子进程结束之后马上在内存中释放资源,主进程就没有办法监测子进程的状态。

    Unix针对上面的问题,提供了一种机制:

    所有的子进程结束后,立马释放掉文件的操作链接、内存等的大部分数据,但是会保留一些内容:进程号、结束时间、运行状态,等待子进程监测、回收。

    僵尸进程:子进程在结束后,主进程并没有调用wait或waitpid获取子进程的状态信息,子进程仍然保留了一些描述内容,这种进程被称为僵尸进程。

    ​ 危害:如果父进程不对僵尸进程进行回收(wait/waitpid),产生大量的僵尸进程,这样会占用内存,占用进程的pid号。

    6.2 孤儿进程

    父进程由于某种原因结束,但子进程还在运行中,则称这些子进程为孤儿进程。

    回收机制:Unix中孤儿进程会被 init 进程回收,init 变成父进程。

    僵尸进程解决方法

    ​ 直接杀死父进程。将所有僵尸进程变成孤儿进程,由 init进程回收。

    7. 守护进程

    # 子进程守护着主进程,只要主进程结束,子进程也跟着结束。
    
    from multiprocessing import Process
    import time
    
    def task(name):
        print(f'{name} is running')
        time.sleep(2)
        print(f'{name} is gone')
    
    if __name__ == '__main__':
        p = Process(target=task, args=('meet',))   # 创建一个进程对象
        p.daemon = True		# 放在start前,否则会报错。
        p.start()
        time.sleep(1)
        print("===主进程")
    """
    meet is running
    ===主进程
    """
    
  • 相关阅读:
    Kubernetes中Pod之间使用虚拟二层网络连接
    ResourceQuota和LimitRange实践指南
    Namespace集群环境的共享与隔离
    K8s生产架构
    K8s常用命令整理+名词解析
    K8s中的pv&&pvc
    Kubernetes保证集群内节点和网络安全
    Kubernetes中网络相关知识
    kubectl常用命令
    物理ceph集群+K8s
  • 原文地址:https://www.cnblogs.com/liwenhu/p/11401655.html
Copyright © 2011-2022 走看看