###并行和并发
并发:一个cpu同一时间不停执行多个程序
并行:多个cpu同一时间不停执行多个程序
cpu的进程调度方法
先来先服务fcfs(first come first server):先来的先执行
短作业优先算法:分配的cpu多,先把短的算完
时间片轮转算法:每一个任务就执行一个时间片(时间段)的时间.然后就执行其他的.
多级反馈队列算法
越是时间长的(例如下载),cpu分配的资源越少,优先级靠后
越是时间短的,cpu分配的资源越多
###同步 异步
场景在多任务当中
同步:必须等我这件事干完了,你在干,只有一条主线,就是同步
异步(由进程触发):没等我这件事情干完,你就在干了,有两条主线,就是异步
###进程(Process)
进程就是正在运行的程序,它是操作系统中,资源分配的最小单位.
一个程序等于一个进程
进程(程序)是由CPU执行
进程是典型的异步过程,可以让CPU执行多个程序
资源分配:分配的是cpu和内存等物理资源
进程号(类似于身份证号码)是进程的唯一标识
同一个程序执行两次之后是两个进程
例如:
#CPU执行的时候只执行就绪状态
(1)就绪(Ready)状态
只剩下CPU需要执行外,其他所有资源都已分配完毕 称为就绪状态。
(2)执行(Running)状态
cpu开始执行该进程时称为执行状态。
(3)阻塞(Blocked)状态
由于等待某个事件发生而无法执行时,便是阻塞状态,cpu执行其他进程.例如,等待I/O完成input,sleep,三次握手(监听)申请缓冲区不能满足等等。
进程使用的基本语法
#from multiprocessing import Process(使用进程必须引入)
#查看进程号必须要引入os模块
#如果父进程是一个程序,子进程就是这个程序中的一部分程序
import os
当前进程id(子进程的进程号)
res = os.getpid()
print(res)
当前进程的父进程id(父进程的进程号)
res2 = os.getppid()
print(res2)
创建进程
process(属于进程类) 永远只创建子进程,返回进程的对象p,
target指定要执行的任务
args指定传递的参数,args的类型是元组,多个参数之间用逗号隔开
创建一个子进程的时候,创建的子进程会有短暂的阻塞,CPU会向下执行,创建的子进程会比主文件执行的要慢一点,呈现出异步现象.
创建的子进程与原进程的数据是隔离
创建子进程一分配空间会有阻塞(只是比较短暂)
创建无参数进程(基于当前文件(父进程),子进程在创建一个子进程,相当于创建的子进程在新的文件中开辟执行,属于不同的程序,并且彼此的数据是独立的,不互通)
def func():
print("1.子进程id>>>>{} , 2.父进程id>>>>{}".format(os.getpid(),os.getppid()))
#windows里面下面这句话必须要加;
if __name__ == "__main__": ===>if下面打印的是主文件中的子父进程
print("3.子进程id>>>>{} , 4.父进程id>>>> {}".format(os.getpid(),os.getppid()))
# 子进程在创建(定义)子进程(异步),返回一个进程对象,执行func任务
p = Process(target = func) # target指定任务
# 调用子进程
p.start()
创建带有参数的进程(程序) (基于当前文件(父进程),子进程在创建一个子进程,相当于创建的子进程在新的文件中开辟执行,属于不同的程序,并且彼此的数据是独立的,不互通)
def func(n):
for i in range(1,n+1):
print("3.子进程id>>>>{} , 4.父进程id>>>> {}".format(os.getpid(),os.getppid()))
if __name__ == "__main__":
print("1.子进程id>>>>{} , 2.父进程id>>>> {}".format(os.getpid(),os.getppid()))
n = 5
# 创建子进程,target指定任务(函数)如果有参数,要通过args给出参数(元组),参数为1个,args就给出一个,如果是两个,args就给出两个,中间用逗号隔开
p = Process(target=func,args=(n,))
# 调用子进程
p.start()
for i in range(1,n+1):
print("*" * i)
多个进程可以异步并发(一个cpu执行多个进程(程序)),子父进程之间的关系
默认一个CPU执行多个进程时,父进程要等到所有子进程结束后在关闭程序(父进程没有了,子进程也不能存在),因为cpu调度策略问题,不一定先执行谁或者后执行谁,整体而言,主进程速度快于子进程,cpu遇到阻塞立刻切换其他任务,等到进程的就绪态在切换回来,主程序会默认等待所有的子进程执行结束之后,在关闭程序,释放资源,若不等待,子进程并不方便管理,容易造成僵尸进程,在后台不停的占用系统的资源(cpu和内存),不清楚进程的来源.
def func(args):
print("3.子进程id>>>>{} , 4.父进程id>>>>{}".format(os.getpid(),os.getppid()) , args)
if __name__ == "__main__":
for i in range(1,11): ===>创建10个进程,每个创建的子进程的参数不一样
Process(target=func,args = (i,)).start()
print("主进程执行结束 .... ")
###join
#如何判断所有的子进程都结束,主进程才能执行并且关闭程序用join
功能:等待所有子进程全部执行完毕之后,主进程任务在继续执行,(用来同步子父进程速度的)
multi 代表多 , Process 属于一个类
join 的基于语法
(1)单个子进程配合join使用
def func():
print("发送第一封邮件")
if __name__ == "__main__":
p = Process(target=func)
p.start()
# 必须等待子进程执行结束之后,在继续执行主程序中的代码,用来同步代码一致性的;
p.join()
print("发送第二封邮件")
(2) 多个子进程配合join使用
def func(index):
print("发送第%s封邮件" % (index))
if __name__ == "__main__":
lst = []
for i in range(10): ====>创建10个不同的异步进程
p = Process(target=func,args=(i,))
p.start() ====>所有异步进程同时进行(速度快)
lst.append(p)
# p.join()# 程序会变成同步阻塞,减慢的速度
for i in lst: ====>等到所有异步执行完以后,在去同步阻塞(不要先去阻塞)
print(i)
i.join()
print("主进程发最后一封邮件,里面的内容是我发完了")
###使用自定义类的方式创建进程(拓展,了解)
自定义类创建进程要求:
(1) 必须继承Process这个父类
(2) 所有进程执行任务的逻辑要写run方法里面
基本语法
class MyProcess(Process):
def run(self):
print("1.子进程id>>>>{} , 2.父进程id>>>>{}".format(os.getpid(),os.getppid()))
if __name__ == "__main__":
p = MyProcess()
p.start()
print("3.子进程id>>>>{} , 4.父进程id>>>>{}".format(os.getpid(),os.getppid()))
有参数的进程函数
class MyProcess(Process):
def __init__(self,arg):
# 手动调用一下父类的构造方法(实现进程的创建)
super().__init__()
self.arg = arg
def run(self):
print("1.子进程id>>>>{} , 2.父进程id>>>>{}".format(os.getpid(),os.getppid()),self.arg)
if __name__ == "__main__":
p = MyProcess("我是参数")
p.start()
print("3.子进程id>>>>{} , 4.父进程id>>>>{}".format(os.getpid(),os.getppid()))
###守护进程
守护进程守护的是主进程,如果主进程执行结束了,意味着守护进程的寿命立刻终止.立刻杀死
语法:
进程.daemon = True 设置当前进程为守护进程
必须写在start()调用进程之前进行设置
默认情况下,主进程会等待所有子进程执行完毕之后,关闭程序,释放资源
守护进程在主进程代码执行结束之后,直接杀掉.非守护进程,主进程还是会默认等待的.
基本用法
def func():
print("start 当前子进程")
print("end 当前子进程")
if __name__ == "__main__":
p = Process(target=func)
p.daemon = True
p.start()
print("主进程执行结束 ... ")
多个子进程的场景
import time
def func1():
count = 1
while True:
print("*" * count)
time.sleep(0.5)
count += 1
def func2():
print("start func2当前子进程")
time.sleep(2)
print("end func2当前子进程")
if __name__ == "__main__":
p1 = Process(target=func1)
p2 = Process(target=func2)
# 设置当前进程为守护进程
p1.daemon = True
p1.start()
p2.start()
time.sleep(1)
# 非守护进程,主进程还是会默认等待的.
print("主程序代码结束....")
守护进程的实际用途: 监控报活
import time
监控报活 ===>随时记录5号功能报告给监控服务器
def alive():
while True:
print("给监控服务器发消息, 当前5号服务器功能正常 i am ok ~")
time.sleep(1)
当前服务器正常完成的功能(记录报表)
def func():
# while True:
time.sleep(5)
print("当前5号服务器功能,统计财务报表~")
if __name__ == "__main__":
p1 = Process(target=func) ====>如果有一天这个服务器炸了,停止运行,就会走主文件的代码
p2 = Process(target=alive) ==>监控报活必须跟着服务器走
p2.daemon = True
p1.start()
p2.start()
# 等待p1子进程执行结束之后,下面的主程序的代码才会放行;
p1.join()
print("当前服务器状态:统计财务报表功能异常.....")