zoukankan      html  css  js  c++  java
  • python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程

    python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程

    1. 进程创建的两种方式

    • 开启进程的第一种方式

      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=('张三',))   # 创建一个进程对象
          p.start()
          print('==主开始')
        
          
      # 1.在window环境下,开启进程必须__name=='__main__'下面
      #   原因:这是 Windows 上多进程的实现问题。在 Windows 上,子进程会自动 import 启动它的这个文件,而在 import 的时候是会执行这些语句的。如果你这么写的话就会无限递归创建子进程报错。所以必须把创建子进程的部分用那个 if 判断保护起来,import 的时候 __name__ 不是 __main__ ,就不会递归运行了。
      
      # 2.p.start()
      #   只是向操作系统发出一个开辟子进程的信号,然后就执行下一行了,这个信号操作系统接收到之后,会从内存中开辟子进程空间,然后再将主进程所有数据copy加载到子进程,然后再调用CPU去执行.
      
      # 3.开辟子进程开销是很大的,所以永远会先执行主进程的代码
      
    • 开启进程的第二种方式

      from multiprocessing import Process
      import time
      
      class MyProcess(Process):
      
          def __init__(self,name):
              super().__init__()
              self.name = name
      
          def run(self):
              print(f'{self.name} is running')
              time.sleep(2)
              print(f'{self.name} is gone')
      
      
      if __name__ == '__main__':
          p = MyProcess('张三')
          p.start()
          print('===主')
      
    • 简单应用

      from multiprocessing import Process
      import time
      
      def task(name):
          print(f'{name} is running')
          time.sleep(1)
          print(f'{name} is gone')
      
      def task1(name):
          print(f'{name} is running')
          time.sleep(2)
          print(f'{name} is gone')
      
      def task2(name):
          print(f'{name} is running')
          time.sleep(3)
          print(f'{name} is gone')
      
      
      if __name__ == '__main__':
          # 一个进程串行的执行三个任务
          start_time = time.time()
          task('张三')
          task1('李四')
          task2('王五')
          print(f'结束时间{time.time() - start_time}')
          
          # 三个进程 并发或者并行的执行三个任务
          start_time = time.time()
          p1 = Process(target=task, args=('李四',))   # 创建一个进程对象
          p2 = Process(target=task1, args=('王五',))  # 创建一个进程对象
          p1.start()
          p2.start()
          task2('张三')
          print(f'结束时间{time.time()-start_time}')
      

    2. 进程PID

    • pid是进程在内存中的唯一标识

    • pid的获取:

      命令行获取所有的进程的pid:tasklist;命令行获取某个进程的pid:tasklist|findstr python

      代码级别获取一个进程的pid

      import os
      print(os.getpid())
      

      获取父进程(主进程)的pid

      import os
      print(f'子进程:{os.getpid()}')
      print(f'主(父)进程:{os.getppid(())}')
      
    • 验证进程之间的空间隔离

      from multiprocessing import Process
      import time
      name = '张三'
      
      def task():
          global name
          name = '李四'
          print(f'子进程{name}')
      
      
      if __name__ == '__main__':
          p = Process(target=task)  # 创建一个进程对象
          p.start()
          # print('==主开始')
          time.sleep(3)
          print(f'主:{name}')
          
      # 不能共享内存的数据
      

    3. 进程对象join方法

    • join让主进程等待子进程结束后,再执行主进程(lock,队列)

    • 示例一:简单使用

      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=('太阳',))  # 创建一个进程对象
          p.start()
          p.join()
          print('==主开始')
      
    • 示例二:多个子进程使用join

      # 未使用join耗时
      from multiprocessing import Process
      import time
      
      def task(name,sec):
          print(f'{name}is running')
          time.sleep(sec)
          print(f'{name} 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()
          print(f'==主{time.time()-start_time}')  # 0.02 这只是主进程结束的时间,与其他进程毫无关系
          
      # 验证1:使用join,测试多个join之后的结果以及耗时
      from multiprocessing import Process
      import time
      
      def task(name,sec):
          print(f'{name}is running')
          time.sleep(sec)
          print(f'{name} 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}')
      
      # 结果:
      张三is running
      李四is running
      王五is running
      张三 is gone
      李四 is gone
      王五 is gone
      ==主3.2888922691345215
      
      # 验证2:使用join,测试多个join之后的结果以及每个join之后的耗时
      from multiprocessing import Process
      import time
      
      def task(name,sec):
          print(f'{name}is running')
          time.sleep(sec)
          print(f'{name} 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'==主1:{time.time()-start_time}')
          p2.join()
          print(f'==主2:{time.time()-start_time}')
          p3.join()
          print(f'==主3:{time.time()-start_time}') 
          
      # 结果:
      张三is running
      李四is running
      王五is running
      张三 is gone
      李四 is gone
      王五 is gone
      ==主1:3.2728402614593506
      ==主2:3.2728402614593506
      ==主3:3.2728402614593506
      
    • 优化使用多个join方法时的注意事项

      # 优化此方法
      from multiprocessing import Process
      import time
      
      def task(sec):
          print(f'is running')
          time.sleep(sec)
          print(f' 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()
          
          # 错误示范:这样就是串行,一个执行完执行下一个
          for i in range(1,4):
              p = Process(target=task,args=(i,))
              p.start()
              p.join()
          p1 = Process(target=task,args=(1,))
          p1.start()
          p1.join()
          p2 = Process(target=task,args=(2,))
          p2.start()
          p2.join()
          p3 = Process(target=task,args=(3,))
          p3.start()
          p3.join()
      
          
          # 正确示范:
          l1 = []
          for i in range(1, 4):
              p = Process(target=task,args=(i,))
              l1.append(p)
              p.start()
          
          for i in l1:
              i.join()
          
          print(f'==主{time.time()-start_time}')
      
      # join就是阻塞,主进程有join,主进程下面的代码一律不执行,直到进程执行完毕之后,再执行.
      

    4. 进程对象其他属性

    • 常见属性释义:

      p.terminate() :杀死子进程

      print(p.is_alive()) :判断子进程是否存活

      p.name = '子进程2' :给子进程设置名称

    • 代码示例:terminate/is_alive/p.name

      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=('张三',),name='子进程')  # 创建一个进程对象,其中的name='子进程'是给该进程设置名字为子进程
          p.start()
          time.sleep(1)
          p.terminate()    # 杀死子进程  ***
          p.join()  # ***
          time.sleep(0.5)
          print(p.is_alive())   # 判断子进程是否存活 ***
          print(p.name)
          p.name = '子进程2'    # 给子进程设置名称
          print(p.name)
          print(p.pid)         # 查看pid
          print('==主开始')
      

    5. 守护进程

    • 守护进程:子进程守护着主进程,只要主进程结束,子进程就跟着结束

    • 代码示例:

      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=('太阳',))  # 创建一个进程对象
          p.daemon = True  # 将p子进程设置成守护进程,只要主进程结束,守护进程马上结束.
          p.start()
          # p.daemon = True  # 一定要在子进程开启之前设置
          time.sleep(1)
          print('===主')
      
  • 相关阅读:
    Candy leetcode java
    Trapping Rain Water leetcode java
    Best Time to Buy and Sell Stock III leetcode java
    Best Time to Buy and Sell Stock II leetcode java
    Best Time to Buy and Sell Stock leetcode java
    Maximum Subarray leetcode java
    Word Break II leetcode java
    Word Break leetcode java
    Anagrams leetcode java
    Clone Graph leetcode java(DFS and BFS 基础)
  • 原文地址:https://www.cnblogs.com/liubing8/p/11386143.html
Copyright © 2011-2022 走看看