进程和线程
什么是进程?
进程就是正在运行的程序, 一个任务就是一个进程, 进程的主要工作是管理资源, 而不是实现功能
什么是线程?
线程的主要工作是去实现功能, 比如执行计算.
线程和进程的关系就像员工与老板的关系,
老板(进程) 提供资源 和 工作空间,
员工(线程) 负责去完成相应的任务
特点
一个进程至少由一个线程, 这一个必须存在的线程被称为主线程, 同时一个进程也可以有多个线程, 即多线程
当我们我们遇到一些需要重复执行的代码时, 就可以使用多线程分担一些任务, 进而加快运行速度
线程的实现
线程模块
Python/ target=_blank class=infotextkey>Python通过两个标准库_thread和threading, 提供对线程的支持 , threading对_thread进行了封装。
threading模块中提供了Thread , Lock , RLock , Condition等组件。
因此在实际的使用中我们一般都是使用threading来实现多线程
线程包括子线程和主线程:
主线程 : 当一个程序启动时 , 就有一个线程开始运行 , 该线程通常叫做程序的主线程
子线程 : 因为程序是开始时就执行的 , 如果你需要再创建线程 , 那么创建的线程就是这个主线程的子线程
主线程的重要性体现在两方面 :
是产生其他子线程的线程
通常它必须最后完成执行, 比如执行各种关闭操作
Thread类
常用参数说明
常用实例方法
创建线程
在python中创建线程有两种方式, 实例Thread类和继承重写Thread类
实例Thread类
继承Thread类
常用方法
join()
阻塞调用程序 , 直到调用join () 方法的线程执行结束, 才会继续往下执行
setDemon()
使用给线程设置守护模式: 子线程跟随主线程的结束而结束, 不管这个子线程任务是否完成. 而非守护模式的子线程只有在执行完成后, 主线程才会执行完成
setDaemon() 与 join() 基本上是相对的 , join会等子线程执行完毕 ; 而setDaemon则不会等
线程间的通信
互斥锁
在同一个进程的多线程中 , 其中的变量对于所有线程来说都是共享的 , 因此 , 如果多个线程之间同时修改一个变量 , 那就乱套了 , 共享的数据就会有很大的风险 , 所以我们需要互斥锁 , 来锁住数据 , 防止篡改。
来看一个错误的示范:
下面我们改一下上面的代码 , 两个方法加上互斥锁:
在容易出现抢夺资源的地方进行上锁 , 实现同一时间内 , 只有一个线程可以对对象进行操作
队列Queue
常用方法
关键字解释
(1): 阻塞: 程序停在阻塞的位置 , 无法继续执行
导入和实例化
put() 和 get()
empty()
qsize()
full()
join()
线程池
池的概念
线程池中实现准备好了一些可以重复使用的线程 , 等待接受任务并执行
主线程提交任务给 线程池 , 线程池中的每个线程会一次一个的接收任务并执行 , 直到主线程执行结束
主线程: 相当于生产者,只管向线程池提交任务。
并不关心线程池是如何执行任务的。
因此,并不关心是哪一个线程执行的这个任务。
线程池: 相当于消费者,负责接收任务,
并将任务分配到一个空闲的线程中去执行。
自定义线程池
简单使用
python内置线程池
原理
1.创建线程池
2.将任务扔进去
3.关闭线程池
4.等待线程任务执行完毕
使用方法
其他操作
操作一: close - 关闭提交通道,不允许再提交任务
操作二: terminate - 中止进程池,中止所有任务