Python多进程、多线程、协程编程

Python进程(Process)、线程(Thread)、协程(asyncio)编程

一、多进程编程
  • 进程概念

    进程是计算机操作系统进行资源分配的基本单位,是一个程序的执行实例,也就是正在执行的程序。在OS的眼里,进程就是一个担当分配系统资源CPU时间、内存的实体。一般来说,系统会由一组进程组成:操作系统进程执行系统代码,而用户进程执行用户代码,计算机通过 CPU 的多路复用,所有这些进程可以并发执行,因此进程的可执行数量和CPU性能有关。

    1、进程的基本状态

    • 就绪:进程的就绪状态是指一个进程已经具备除处理器(CPU)之外的所有执行条件
    • 运行:进程的就绪状态是指进程得到了处理器,并不需要等待其他任何资源,正在执行的状态
    • 阻塞:进程阻塞状态也称进程等待状态,是指进程等待某一特定事件的出现(如I/O操作),在该过程中,进程依旧位于内存内,且占有CPU资源

    2、图示

    在这里插入图片描述

  • Process基本使用示例

    • Process简介

      python内置的multiprocessing模块提供了类来方便用户创建一个多进程,其基本结构和参数如下:

      • 结构

        calss multiprocessing.Process(group=None, target=None, name=None, args=(),kwargs={}, *, daemon=None)
        
      • 参数

        • target: 调用对象,一般为函数、类,是进程的执行实体
        • name: 进程的别名
        • args:调用对象的位置参数元组
        • kwargs:调用对象的字典
        • group:基本不使用,忽略
      • Process类提供的方法

        • is_alive(): 返回进程是否激活
        • join(]): 阻塞进程,直到进程执行完成或者终止
        • run(): 进程运行的函数,可以被重写
        • start(): 激活进程,进程开始运行
        • terminate(): 进程终止
    • 创建一个Process进程

      import os
      import time
      from multiprocessing import Process
      
      def task_process(delay):
          num = 0
          for i in range(delay * 100000):
              num += i
          print(f"进程:{os.getpid()},执行完成")
      
      
      if __name__ == '__main__':
          print('父进程为%s.' % os.getpid())
          t0 = time.time()
          # 单线程
          task_process(3)
          task_process(4)
          t1 = time.time()
          print(f"单线程顺序执行耗时{t1 - t0}")
          # 多线程
          p0 = Process(target=task_process, args=(3,))
          p1 = Process(target=task_process, args=(4,))
          t2 = time.time()
          p0.start()
          p1.start()
          p0.join()
          p1.join()
          t3 = time.time()
          print(f"多线程并发执行耗时{t3 - t2}")
      
    • 创建一个自定义进程继承Process

      import os
      import time
      from multiprocessing import Proces
      
      class self_process(Process):
          def __init__(self, delay):
              self.delay = delay
              super().__init__()
      
          def run(self):
              num = 0
              for i in range(self.delay*10000):
                  num += i
              print(f"进程:{os.getpid()},执行完成")
      
      if __name__ == '__main__':
          print('父进程为%s.' % os.getpid())
          print("自定义线程")
          t0 = time.time()
          for i in range(5):
              q0 = self_process(i)
              q0.start()
              q0.join()
          t1 = time.time()
          print(f"自定义线程执行耗时{t1 - t0}")
      
  • 线程概念

    线程也称轻量级进程,线程是操作系统进行运算调度的最小单位,一般来说一个进程包含多个线程,至少包含一个线程,即线程是进程的实际运作单位,线程自身并不用于系统资源,仅仅需要必备的基本资源,但是线程之间可以共享属于同一个进程的全部资源,同一个进程中的线程可以并发执行,一个线程可以创建和销毁另一个线程,因此,多线程中,一个线程异常可能会导致整个多线程异常,但是多进程不会,因为各个进程的资源是独立的。

    1、线程的基本状态

    • 就绪:线程的就绪状态是指一个线程已经具备运行的所有条件,等待处理机,逻辑上已经可以运行
    • 运行:线程的就绪状态是指线程占有处理机,并且正在执行的状态
    • 阻塞:线程阻塞状态是指线程等待某一特定事件或者信号量 ,逻辑上不可运行

    2、图示

    在这里插入图片描述

  • Thread基本使用示例

    • Thread简介

      python提供Thread类实现线程功能,其基本结构和参数和进程一致,如下:

      • 结构

        class Thread(group=None, target=None, name=None, args=(), kwargs={})
        
      • 参数

        • target: 调用对象,一般为函数、类,是进程的执行实体
        • name: 进程的别名
        • args:调用对象的位置参数元组
        • kwargs:调用对象的字典
        • group:基本不使用,忽略
      • Process类提供的方法

        • is_alive(): 返回进程是否激活
        • join(]): 阻塞进程,直到进程执行完成或者终止
        • run(): 进程运行的函数,可以被重写
        • start(): 激活进程,进程开始运行
        • terminate(): 进程终止
    • 创建一个Thread线程

      import os
      import time
      import threading
      
      def task_process(delay):
          num = 0
          for i in range(delay * 100000):
              num += i
          print(f"线程:{threading.current_thread().name},执行完成")
      
      
      if __name__ == '__main__':
          print(f"主线程为:{threading.main_thread().name}")
          t0 = time.time()
          # 多线程
          p0 = threading.Thread(target=task_process, args=(3,))
          p1 = threading.Thread(target=task_process, args=(4,))
          t2 = time.time()
          p0.start()
          p1.start()
          p0.join()
          p1.join()
          t3 = time.time()
          print(f"多线程并发执行耗时{t3 - t2}")
      
    • 创建一个自定义Thread线程继承Thread类

      import os
      import time
      import threading
      
      class thread_process(threading.Thread):
          def __init__(self, delay):
              self.delay = delay
              super().__init__()
      
          def run(self):
              num = 0
              for i in range(self.delay * 10000):
                  num += i
              print(f"线程:{threading.current_thread().name},执行完成")
      
      
      if __name__ == '__main__':
          print(f"主线程为:{threading.main_thread().name}")
          print("自定义线程")
          t0 = time.time()
          for i in range(5):
              q0 = thread_process(i)
              q0.start()
              q0.join()
          t1 = time.time()
          print(f"自定义线程执行耗时{t1 - t0}")
      
三、协程编程
  • 协程概念

    协程是轻量级的线程,拥有自己的寄存器和栈,协程调度切换时,将寄存器上下文和栈保存到其他地方,切回来时,恢复之前保存的状态,因此协程能够保留上一次调用的状态信息,即每次过程重入,相当于进入上一次调用状态。协程适用于IO密集型任务处理,因为协程是基于线程的,其调用是在一个线程中进程,是单线程操作,因此效率略高于多线程。

  • asyncio基本使用示例

    • asyncio简介

      python常用的协程库比如asyncio,结合python的async/await,能够很方便的使用协程操作。

    • 基本使用

      import asyncio
      import time
      
      
      async def task():
          print(f"{time.strftime('%H:%M:%S')} task 开始")
          await asyncio.sleep(1)
          print(f"{time.strftime('%H:%M:%S')} task 结束")
      
      
      loop = asyncio.new_event_loop()
      asyncio.set_event_loop(loop)
      tasks = [task() for _ in range(5)]
      start = time.time()
      loop.run_until_complete(asyncio.wait(tasks))
      loop.close()
      end = time.time()
      print(f"用时{end - start}秒")
      
四、区别和联系以及应用场景
  • 区别和联系

    类型区别和联系不同点
    多进程能同时处理多个任务,多进程目的是充分使用CPU性能,完成多个任务的处理,
    适合用于大量计算的任务(计算密集型),于线程的联系是进程包含线程。
    一个进程至少包含一个线程,线程是进程运行实体。
    多线程能同时处理多个任务,线程是操作系统进行运算调度的最小单位,被包含于进程之中。
    线程能够共享同一进程的资源,因此使用多线程能够极大的提高资源的利用率,让程序响应更快。
    协程能同时处理多个任务,协程是轻量级线程,是单线程,
    协程的调度处理都在一个线程内进行,即线程包含协程,
    协程的效率略高于线程,同线程一样,适用于IO密集型任务处理。
  • 应用场景重复计算分类及其选择

      • 计算密集型 - 多进程/协程 - CPU利用率

        计算密集型就是计算、逻辑判断量非常大而且集中的类型,因为主要占用CPU资源所以又叫CPU密集型,而且当计算任务数等于CPU核心数的时候,是CPU运行效率最高的时候,因此计算密集型任务特别消耗CPU。

      • IO密集型 - 多线程 - 网络(输入/输出)

        IO密集型即在计算和处理时需要频繁大量的输入输出输出操作的类型,比如磁盘的读取数据和输出数据非常大的时候就是属于IO密集型,由于IO操作的运行时间远远大于CPU、内存运行时间,所以任务的大部分时间都是在等待IO操作完成,IO的特点是CPU消耗小,所以,IO任务越多,CPU效率越高,当然不是越多越好,有一个极限值。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玉言心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值