1.如何理解进程
程序:一堆躺在文件上的死代码
进程:正在被运行的程序(活的)
2.进程的调度算法
先来先服务算法
针对耗时比较短的程序不友好
短作业优先调度
针对耗时比较长的程序不友好
时间片轮转法+多级反馈队列
将固定的时间均分成很多份 所有的程序来了都公平的分一份
分配多次之后如果还有程序需要运行 则将其分到下一层
越往下表示程序总耗时越长 每次分的时间片越多 但是优先级越低
并行:多个进程同时执行,单个CPU肯定无法实现并行 必须要有多个CPU。
并发:多个进程看上去像同时执行就可以称之为并发,单个CPU完全可以实现并发的效果 如果是并行那么肯定也属于并发。
1.所有的进程要想被运行 必须先经过就绪态
2.运行过程中如果出现了IO操作 则进入阻塞态
3.运行过程中如果时间片用完 则继续进入就绪态
4.阻塞态要想进入运行态必须先经过就绪态
用于描述任务的提交状态
同步:提交完任务之后原地等待任务的结果 期间不做任何事
异步:提交完任务之后不原地等待直接去做其他事 结果自动提醒
用于描述进程的执行状态
阻塞:阻塞态
非阻塞:就绪态 运行态
同步阻塞:在银行排队 并且在队伍中什么事情都不做
同步非阻塞:在银行排队 并且在队伍中做点其他事
异步阻塞:取号 在旁边座位上等着叫号 期间不做事
异步非阻塞:取号 在旁边座位上等着叫号 期间为所欲为
方式一:
from multiprocessing import Process import time def test(name): print(f'{name}正在执行') time.sleep(3) print(f'{name}执行结束') if __name__ == '__main__': p = Process(target=test, args=('jasper',)) p.start() print('主进程结束')
方式二:
class MyProcess(Process): def __init__(self, name): super().__init__() self.name = name def run(self): print(f'{self.name}正在执行') time.sleep(3) print(f'{self.name}执行结束') if __name__ == '__main__': p = MyProcess('jasper') p.start() print('主进程结束')六 join方法
主进程等待子进程运行结束后在运行
from multiprocessing import Process import time def test(name): print(f'{name}正在执行') time.sleep(3) print(f'{name}执行结束') if __name__ == '__main__': p1 = Process(target=test, args=('jasper',)) p2 = Process(target=test, args=('lili',)) p3 = Process(target=test, args=('jack',)) p1.start() p1.join() p2.start() p2.join() p3.start() p3.join() print('主进程结束')七 进程间数据默认隔离
多个进程之间数据是相互隔离的
from multiprocessing import Process money = 1000 def test(): global money money = 9999 print(money) # 9999 if __name__ == '__main__': p = Process(target=test) p.start() print(money) # 1000八 进程间通信(ipc机制)
from multiprocessing import Queue # 创建一个队列对象 参数是最大存取数据个数 q = Queue(3) q.put(1) # 往队列中添加数据 q.put(2) q.put(3) # q.put(4) # 超出队列最大数据个数 会进入阻塞状态 等待数据被取走 print(q.get()) # 获取队列中的数据 print(q.get()) print(q.get()) # print(q.get()) # 超出队列中最大数据个数 会进入阻塞状态 等待数据添加 print(q.empty()) # 判断队列是否为空 print(q.full()) # 判断队列是否满了 # q.get_nowait() # 获取数据 如果没有直接报错 # q.put_nowait() # 添加数据 如果满了直接报错 # print(q.qsize()) # 获取队列中数据个数
from multiprocessing import Process, Queue def test1(q): print(f'主进程传来的数据:{q.get()}') def test2(q): q.put('test添加的数据') print('添加消息成功') if __name__ == '__main__': q = Queue() p1 = Process(target=test2, args=(q,)) p1.start() p2 = Process(target=test1, args=(q,)) p2.start() p1.join() p2.join() print('主进程结束')九 生产者消费者模型
生产者:产生数据
消息队列/数据库
消费者:处理数据
from multiprocessing import current_process, Process import os import time print(current_process().pid) # 获取当前进程号 print(os.getpid()) # 获取当前进程号 print(os.getppid()) # 获取当前进程的父进程号 def test(name): print(f'{name}正在执行') time.sleep(3) print(f'{name}执行结束') if __name__ == '__main__': p = Process(target=test, args=('jasper',)) p.start() p.terminate() # 结束子进程 # print(p.is_alive()) # True time.sleep(0.01) print(p.is_alive()) # 判断进程是否存活 False print('主进程结束')十一 守护进程
伴随着守护的对象存活而存活,结束而结束。
from multiprocessing import Process import time def test(name): print(f'{name}正在执行') time.sleep(3) print(f'{name}执行结束') if __name__ == '__main__': p = Process(target=test, args=('jasper',)) p.daemon = True # 必须在start前面设置 p.start() time.sleep(3.2) print('主进程结束')十二 僵尸进程和孤儿进程
僵尸进程:进程已经运行结束,但是相关的资源并没有完全清空,需要父进程参与回收。
孤儿进程:父进程以为结束,子进程正常运行。