多任务之进程浅谈
一、进程及状态
1、进程
程序,是指静态,而进程则是动态的概念,首先把程序运行起来,代码+涉及的资源=进程,它是操作系统分配资源的基本单位,多进程可以实现多任务
2、进程的状态
1、就绪态:一切准备好,只等待CPU的调度
2、运行态:CPU正在执行本进程的代码
3、等待态:等待某个条件的满足,比如sleep,socket.recvfrom,互斥锁的解锁,等待红绿灯,条件满足则进入就绪态
二、进程的创建-multiprocessing(重点)
1、multiprocessing模块介绍:multiprocessing模块就是跨平台版本的多进程模块,提供了一个Process类来创建进程对象
2、通过multiprocessing模块创建子进程
实现步骤:
1、导入multiprocessing模块
2、准备用于封装任务的函数
3、通过multiprocessing.Process()创建子进程target=function
4、执行子进程
参考代码如下:
3、获取进程的id
a>通过Linux命令方式查看进程id:ps -aux | grep ‘02-’
b>通过代码方式查看进程id
当前的子进程是有主进程创建的
os.getpid():取得当前进程的id
os.getppid():取得父进程id(创建当前进程的进程id)
print("------in main -----当前进程id=%d,父进程id=%d“%(os.getpid(), os.getppid()))
4. Process语法结构
a> Process([group [, target [, name [, args [, kwargs]]]]])
"""Process初始化参数"""
- target: 目标,指向, 表示子进程要执行的代码在target指向的函数中
- args:向target指向的函数传递不定参数, 以元组类型来封装这些不定参数
- kwargs:向target指向的函数传递关键字参数,以字典类型来封装这些关键字参数
b> 进程对象常用的属性、方法
- process.name: 进程的名称
- process.pid: 进程的id
- process.start() : 执行进程
- process.is_alive(): 进程是否是活的
- process.join(timeout) : 阻塞当前进程(主进程),等待子进程执行完毕,再解阻塞
# timeout=2 : 最多阻塞主进程2秒,超过2秒,则主进程解阻塞
- process.terminate() :结束子进程的执行
参考代码: 03-向子进程传递参数.py
参考代码: 04-进程的属性和方法.py
5. 进程间不共享全局变量
进程间不共享全局变量
参考代码: 05-进程间不共享全局变量.py
三、进程线程对比
a>功能方面
都能完成多任务
b>定义方面
1. 进程是操作系统进行资源分配和调度的一个基本单位.
2.线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
c>区别
1. 一个程序至少有一个进程,一个进程至少有一个线程.
2.线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高。
3.进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率
4.线程不能够独立执行,必须依存在进程中
d>优缺点
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反
目标的理解: 要实现多任务, 开多线程比开多进程要更好
四、进程间通信-Queue(队列)
1.队列介绍
常用的数据结构,采用先进先出原则(fifo: first inter first outer),从队列的尾部存(put)数据
从队列的头部取(get)数据
2. Queue 的使用
a> queue基本使用
- multiprocess.Queue(maxsize=3)
创建队列对象,maxsize : 设置队列存数据的上限,假如不设置maxsize, 则没有上限的要求
- put(item)
向队列存数据,假如当前队列满,则等待
- get()
从队列取数据,假如当前队列空,则等待
- full(): 判队列是否满
- empty(): 判队列是否空
参考代码: 06-队列queue初体验.py
b> 使用Queue队列实现进程间通信
案例需求: 在父进程中创建两个子进程,一个往Queue里写数据p,y,t,h,o,n一个从Queue里读取数据,实现进程间通信
参考代码: 07-通过队列实现进程间通信.py
五、进程的创建-进程池Pool
1. 进程池作用
控制进程的数量,重复利用进程对象,减少创建和销毁进程的开销
2. 进程池体验
1. multiprocessing.Pool()
创建进程池对象,可以设置进程池的最大值
2. apply_async(func[,args[,kwds]])
apply(func[,args[,kwds]])
申请异步执行任务
- func: 指向要执行的函数
- args:向要执行的函数传递可变参数
- kwds:向要执行的函数传递命名参数
3. close() : 关闭进程池, 不再接收新的任务请求
4. terminate() : 结束进程池中的所有子进程,
5. join(): 阻塞当前进程(主进程),等到进程池中的所有进程执行完毕后,再解阻塞
提示(拓展):
进程池的子进程都是由主进程创建的
且默认都是守护进程
假如要执行完进程池中子进程的任务
必须做:
pool.close()
pool.join() # 阻塞主进程
参考代码: 08-进程池体验.py
3. 进程池中的进程通信
案例需求: 从进程池中子进程,一个往Queue里写数据i,t,c,a,s,t一个从Queue里读取数据,实现进程池进程间的通信
提示:如果要使用Pool创建进程,就需要使用multiprocessing.Manager()中的Queue(),而不是multiprocessing.Queue()