python学习笔记之--python的多线程以及并发操作

python学习笔记之--python的多线程以及并发操作

  • 1、什么是多线程
  • 2、多线程的作用
  • 3、常见的程序运行方式
  • 4、cpu密集与io密集的区别
  • 5、了解GIL全局解释器锁
  • 6、多线程的运用
  • 7、Python中的queue队列
  • 8、生产者-消费者模式
  • 9、线程池的使用
    • 9.1、submit方法:
    • 9.2、map方法

1、什么是多线程

说起进程,就不得不说下程序。程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。

而进程则是执行程序的一次执行过程,它是一个动态的概念。是系统资源分配的单位
通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程是CPU调度和执行的的单位。

注意:很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。如果是模拟出来的多线程,即在一个cpu的情况下,在同一个时间点,cpu只能执行一个代码,因为切换的很快,所以就有同时执行的错局。

2、多线程的作用

能大幅度提高程序的运行效率,优化用户体验,大大地缩短了程序的运行时间

3、常见的程序运行方式

python学习笔记之--python的多线程以及并发操作_第1张图片

4、cpu密集与io密集的区别

python学习笔记之--python的多线程以及并发操作_第2张图片

注意多线程只能进行并发操作,而不能利用多cpu(存在GIL全局解释器锁),利用的也是cpu与io可以并行运行的原理

5、了解GIL全局解释器锁

全局解释器锁(英语:Global Interpreter Lock,缩写GIL)
是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行。
即便在多核心处理器上,使用GIL的解释器也只允许同一时间执行一个线程。
这也是导致python执行速度慢的一个原因
python学习笔记之--python的多线程以及并发操作_第3张图片

表示了同一时刻只有一个线程在执行
python学习笔记之--python的多线程以及并发操作_第4张图片

GIL的作用:主要是为了解决多线程之间数据完整性和状态同步问题
虽然不能利用多核cpu的优势,但是还是可以实现cpu与io并行的操作,也可以大幅提升速度
python学习笔记之--python的多线程以及并发操作_第5张图片
在这里插入图片描述

6、多线程的运用

python学习笔记之--python的多线程以及并发操作_第6张图片

主要用到threading的Thread类

  • target 表示方法名
  • args 表示方法所需的参数
  • Name 表示线程名字

7、Python中的queue队列

python学习笔记之--python的多线程以及并发操作_第7张图片

  • Queue.qsize() 返回队列的大小
  • Queue.empty() 如果队列为空,返回True,反之False
  • Queue.full() 如果队列满了,返回True,反之False
  • Queue.full 与 maxsize 大小对应
  • Queue.get([block[, timeout]])获取队列,timeout等待时间
  • Queue.get_nowait() 相当Queue.get(block=False) // block=False表示当没元素时不等待,直接抛出Empty 异常
  • Queue.put(item) 写入队列,timeout等待时间
  • Queue.put_nowait(item) 相当Queue.put(item,block=False) // block=False表示当没元素时不等待,直接抛出Full异常
  • Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
  • Queue.join() 实际上意味着等到队列为空,再执行别的操作

8、生产者-消费者模式

python学习笔记之--python的多线程以及并发操作_第8张图片

实际上本质就是,定义一个中间的缓冲区作为生产者与消费者交互的通道,比如餐厅这一场景,以柜台为中间件,生产者生产好后,就调用中间件中push的方法,消费者消费完后就调用中间件的pop方法,再加一定的数量限制即可
即由中间件容器创造资源的增删改的操作
消费者就只负责消费商品,进行删的获取操作
生产者就负责生产商品,负责增加的操作

python学习笔记之--python的多线程以及并发操作_第9张图片
python学习笔记之--python的多线程以及并发操作_第10张图片

9、线程池的使用

系统启动一个新线程的成本是比较高的,因为它涉及与操作系统的交互。在这种情形下,使用线程池可以很好地提升性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池,以此来避免过大的线程的创建与销毁的开销
线程池在系统启动时即创建大量空闲的线程,程序只要将一个函数提交给线程池,线程池就会启动一个空闲的线程来执行它。当该函数执行结束后,该线程并不会死亡,而是再次返回到线程池中变成空闲状态,等待执行下一个函数
线程的生命周期
python学习笔记之--python的多线程以及并发操作_第11张图片

线程池使用的是concurrent.futures 下的ThreadPoolExecutor类

  • submit(fn, *args, **kwargs):将 fn 函数提交给线程池。*args 代表传给 fn 函数的参数,*kwargs 代表以关键字参数的形式为 fn 函数传入参数。
  • map(func, *iterables, timeout=None, chunksize=1):该函数类似于全局函数 map(func, *iterables),只是该函数将会启动多个线程,以异步方式立即对 iterables 执行 map 处理。
  • shutdown(wait=True):关闭线程池。
    python学习笔记之--python的多线程以及并发操作_第12张图片

9.1、submit方法:

submit方法将传入的方法交给线程池,后面直接跟参数值或者关键字传值,返回future对象

  • future.result() 方法获取方法的返回值
  • future.add_done_callback(function) 方法在线程任务完成时自动调用回调方法,此为非阻塞的获取线程执行的结果,直接future.result()会导致阻塞线程
  • as_completed 函数,通过这个函数遍历获取future结果的是异步获取结果,即哪个任务先完成就先输出
    python学习笔记之--python的多线程以及并发操作_第13张图片

9.2、map方法

异步执行方法,顺序输出

注意:zip([1,2],[‘a’,’b’]) ==> [(1,’a’),(2,’b’)]

你可能感兴趣的:(python学习笔记,学习,python)