目录
进程:
进程是指正在执行的程序,一个进程可以包含多个线程,是资源分配的最小单位,进程拥有自己的内存空间和系统资源,一个进程中至少要有一个线程
线程:
可以比喻成实际做事情的人,是进程中的一个执行单位,每个线程都是独立的执行流程,如果一个进程中只有一个线程;那这个线程就称为主线程,子线程
协程:
单线程下的并发,比线程还要小,如果开协程,那么消耗的资源更小,不需要进入内核态,因此可以实现更高效的并发执行
进程和线程的关系:
先开进程,在进程里面开线程,进程和线程都是由操作系统调度的
调度算法:
- 先来先服务:按照进程到达的顺序依次执行,非抢占式的调度
- 短作业优先:按照估计的运行时间排序,短的进程先执行,需要预测每个进程的运行时间
- 时间片轮转:每个进程分配一个时间片(通常几十毫秒)执行完时间后进入就绪队列,等待下一次调度,是一种抢占式的调度算法
- 多级反馈队列:将进程分为多个队列,每个队列有一个时间片长度,优先级高的队列时间片短,优先级低的队列时间片长,当进程在队列中等待一段时间后,会逐渐降低优先级,进入优先级更低的队列
i/o密集型:有阻塞,但是不会一直占用CPU的执行权限
计算密集型:没有阻塞,会大量抢占CPU资源
CPU的工作机制
- 当遇到i/o阻塞的时候,会自动剥夺CPU的执行权限
- 当CPU遇到占用时间过长的任务时候,也会剥夺执行权限
""" CPU的工作其实是来回切换的!!''''
并行:
同时执行多个任务,多个处理器同时处理不同的任务,即多个处理器或者多核处理器同时执行多个任务,从而提高了处理效率。在并行处理的情况下,如果每个任务的执行时间是相等的,那么任务的执行时间会被大大缩短。(也可以理解为,多个任务在同一时刻,一起执行)一般很难实现真正意义的并行
并发:
指同时执行多个任务,多个任务会有交替执行或同时执行的情况,但是同一时刻只能有一个任务被执行(并发可以比喻成 赛跑,而并发更像是 接力跑)
高并发:
指的是同时处理大量请求的能力,在计算机中,高并发指的是一个系统在处理高并发请求时,仍然能保持高性能,高并发需要更多的资源和技术支持,才能保证系统的稳定性和可用性
同步和异步是关于消息通讯机制的
同步:
指发送方发出消息后,就必须等对方做出回应,这个期间什么都不做,就只等得到回复才会执行后面的事情
异步:
指发送方发出消息后,不需要等对方做出回应,就可以去做别的事情,可以忙完别的事情再返回查看此次的结果
阻塞和非阻塞是关于程序等待消息时的状态
阻塞:
程序发送消息后,在接收回应前一直处于等待状态,无法执行其他任务
非阻塞:
程序发送消息后,再等待回应的过程中,可以执行其他任务
执行效率:
同步阻塞---->效率最低
异步非阻塞----->效率最高
Process类中的参数:
target
:要执行的函数。args
:一个元组,表示传递给函数的参数。kwargs
:一个字典,表示传递给函数的关键字参数。name
:进程的名称。默认值是一个数字。daemon
:布尔值,表示进程是否为守护进程。默认值为False
。
Process类中的方法(创建并操作进程的类)
start()
:启动进程。调用该方法将会在一个新的进程中执行 target 方法。
join()
:等待进程执行结束。如果 timeout 参数不为 None,则等待 timeout 秒后如果进程还未结束则不再等待。
is_alive()
:判断进程是否正在运行。
terminate()
:终止进程。
getName()
:获取进程的名称。
setName()
:设置进程的名称。
如何查看进程号
- os.getpid():写在哪个进程中,就获取的是这个进程的pid
- os.getppid():获取父进程号
- p.pid():只能获取由multiprocessing.Process对象创建的子进程的进程号,如果尝试在父进程中使用,就会返回None
如何开启多进程
基于TCP的高并发程序
守护进程
p.daemon = True 把p进程设置为守护进程,守护进程是,主进程执行完毕,子进程立马结束
注意:p.daemon = True这行代码必须写在start前面
进程之间数据是隔离的,不能相互使用,修改
如何开启线程
from threading import Thread # 导入模块
def print_numbers():
for i in range(10):
print(i)
thread = threading.Thread(target=print_numbers) # 创建一个线程
thread.start() # 开启线程
进程和线程的比较
- 进程占用的资源远远大于线程
- 进程可以利用多核优势,线程虽然不能,但是可以开多进程,然后进程里面再开线程实现
- 进程之间有数据隔离,线程的数据不隔离,但前提是需要在同一进程内
Thread类中的方法 (创建并操作线程的类)
start()
:启动线程。调用该方法将会在一个新的线程中执行 target 方法。
join()
:等待线程执行结束。如果 timeout 参数不为 None,则等待 timeout 秒后如果线程还未结束则不再等待。
is_alive()
:判断线程是否正在运行。
getName()
:获取线程的名称。
setName()
:设置线程的名称。
多线程实现socket ![](https://i-blog.csdnimg.cn/blog_migrate/25faccef17e3925eaeb565b6f21761e0.png)
守护线程
t.daemon = True 返回一个布尔值
t.setDaemon (True) 接受一个布尔值
当把t 设置为守护线程时,主线程for循环运行结束后,t线程会同时结束
线程队列
同一进程下多个线程是共享的,为什么同一进程下还会去使用队列,因为队列是 管道+锁 能更好的保证数据安全
from multiprocessing import Queue
进程队列:Queueimport queue
线程队列:queue进程Queue用于父进程与子进程(或同一父进程中多个子进程)间数据传递
python自己的多个进程间交换数据或者与其他语言(如Java)进程queue就无能为力queue.Queue 的缺点是它的实现涉及到多个锁和条件变量,因此可能会影响性能和内存效率。
线程队列有3种:
1. 先进先出
2. 先进后出
3. 优先级队列'''优先级队列''' q = queue.PriorityQueue() # put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高 q.put((5, 'a')) # 元组里面的第一个数字代表的是优先级,第二个元素是具体的数据 q.put((15, 'b')) q.put((10, 'c')) print(q.get()) print(q.get()) print(q.get()) ''' 结果(数字越小优先级越高,优先级高的优先出队): (10, 'b') (20, 'a') (30, 'c') '''
进程池和线程池(掌握思路)
池:盛放更多个对象的,盛放更多的进程和线程
'''进程池和线程池都是提供的是异步调用,只需要往池子里丢任务,我们不需要等待结果,等池子里面的任务完成之后,内部做了一个回调,告诉我们执行后的结果!!!'''
进程池:
提前创建一个池子,这个池子里面先创建号一怼进程,然后,只需要向池子里面丢任务就行.线程池:
提前创建一个池子,这个池子里面先创建号一怼线程,然后,只需要向池子里面丢任务就行.
创建池的目的:节省资源,防止内存被沾满的情况,另外就是也能提升效率,但是不能无限的开进程.
线程池爬网页
协程
协程的概念在操作系统中压根不存在,操作系统中有的是进程和线程概念,他们两个都是有操作系统调度
协程是我们程序员调度的,它也称作是用户态的轻量级线程. 用户态---->程序员
'''协程它是单线程下的并发.'''需要下载和安装gevent模块
协程实现高并发
猴子补丁
是指在运行时动态地修改代码的技术。在 Python 中,可以使用猴子补丁来替换掉模块中的某些函数或方法,从而实现一些特殊的功能或调试目的。
from gevent import monkey;
monkey.patch_all() #猴子补丁使用它的作用是自动将标准库中的阻塞式 I/O 操作替换成 gevent 提供的相应的非阻塞式 I/O 操作,从而实现协程并发