文章目录
一、引言
我们之前使用的select能同时监控多个IO事件,当那个事件准备就绪了就执行哪一个,避免了一个IO阻塞造成其它的IO无法执行,提高了执行效率,但是不能够满足多个客户端长期占用服务端的需求,它的适用情况是http请求。
我们现在要学习的并发编程就可以解决现在的问题,实现并发编程的方法:多进程编程,多线程编程。
二、进程
进程的概念起源于操作系统。
(一)操作系统的功能
- 帮我们把硬件复杂的操作封装了:比如对于文件的操作,即对硬盘的操作
- 帮我们管理多个程序的执行(我们一个程序执行的三大硬件:CPU,内存,硬盘 都是由操作系统在操作)
- CPU同时值执行一个任务,任务执行的形式有两种
- 并发,多个任务分配到一个CPU内核,那么多个任务之间就是并发的关系(并发包含并行)
- 并行,多个任务分配到不同的CPU内核上,那么多个任务就是并行的关系
(二)进程的创建
1.进程的概念
正在执行的程序就叫进程。
2.创建
- 用户交互式请求,双击某个应用程序
- 一个进程在运行的过程中又开启另一个程序
在我们自己写的程序在他运行的过程中,开进程执行程序
举个例子:
def func1():
pass
#执行4秒
def func2():
pass
#执行2秒
func1()
func2()
#一个个执行就需要6秒
#一起执行就只需要4秒
3.开进程的方式
# 1. 使用multiprocessing模块帮我们实现多进程编程
import time
from multiprocessing import Process
# 2.将需要新的进程执行的任务封装在一个函数里边
# 我们创建进程的目的是为了执行某件事情
def func():
print("开始执行函数")
time.sleep(2) # 休息两秒钟之后
print("函数执行完成了")
if __name__ == '__main__':
s = time .time() # 获取当前时间戳
print(s)
# 3. 通过Process创建一个对象
p = Process(target=func) # target绑定要执行的函数
# 4.通过进程对象,调用start来启动进程
p.start()
func()
func()
print(time.time() - s) #执行函数所使用的时间
结果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WwW5WLni-1651843955858)(C:\Users\彭兴娇\AppData\Roaming\Typora\typora-user-images\1650460804649.png)]
通过进程我们就可以同时去做多件事情。
- 新的进程是原有进程的子进程,子进程会复制父进程的内存空间。
- 一个进程是可以创建多个子进程的。
- 子进程只执行指定的函数,其它的内容由父进程执行。
- 父进程和子进程的启动时异步的,父进程负责通知操作系统启动子进程
- multiprocessing创建出来的子进程里面是不能使用标准输入的,就是input是用不了的
if __name__ == '__main__':
一个py文件有两个用途:
1.当成文件执行 –main–
2.当成模块导入 模块名称
–name–:是python当中的内置变量,用来区分程序执行的方式
如果没有 if __name__ == '__main__':
这个语句,就不知道怎么来执行它
(三)传参的问题
Process()
功能:创建进程对象
功能:
target:绑定要执行的目标函数,注意给的是函数名,不要加括号
args:需要的是一个元组,用来给target函数传参数
kwargs:需要的是一个字典,用来给target函数传参数
# 1. 使用multiprocessing模块帮我们实现多进程编程
import time
from multiprocessing import Process
# 2.将需要新的进程执行的任务封装在一个函数里边
# 我们创建进程的目的是为了执行某件事情
def func(sec, name):
print("开始执行函数")
for i in range(3):
time.sleep(sec) # 休息两秒钟之后
print("I'm %s"% name)
if __name__ == '__main__':
# 3. 通过Process创建一个对象
p = Process(target=func,args=(1, '海绵宝宝')) # target绑定要执行的函数
# 4.通过进程对象,调用start来启动进程
p.start()
print(time.time() - s) #执行函数所使用的时间
(四)进程之间数据隔离的问题
进程数据隔离指:QQ发消息微信不会收到消息这样的
from multiprocessing import Process
n = 100
def func():
global n
n = 0
print ("子进程里边的n",n)
if __name__ == '__main__': #主进程
p = Process(target=func) #创建一个子进程
p.start() #启动子进程
print("主进程里的n",n)
'''
运行结果:
主进程里的n 100
子进程里边的n 0
'''
启动多个进程
from multiprocessing import Process
def func(arg):
print ("子进程里边的%s",arg)
if __name__ == '__main__': #主进程
for i in range(10):
Process(target=func,args=(i,)).start() #创建多个子进程
'''
运行结果:
子进程里边的%s 1
子进程里边的%s 0
子进程里边的%s 3
子进程里边的%s 4
子进程里边的%s 2
子进程里边的%s 6
子进程里边的%s 5
子进程里边的%s 7
子进程里边的%s 8
子进程里边的%s 9
'''
三、进程类
我们之前创建进程的方式都是把子进程要执行的内容放在一个函数里面
如果说你更喜欢使用面向对象的话 也可以使用类封装进程内容
1.创建子进程的另一种方式
"""
使用类创建的步骤
1. 自己写一个类 继承Process类
2. 重写__init__ 方法添加自己的属性 super继承父类的属性
3. 重写run方法
"""
from multiprocessing import Process
class MyProcess(Process):
def __init__(self, val):
self.val = val
super().__init__() # 调用父类的init方法
def func1(self): # 自己定义的启动进程的步骤
print('步骤1.....', self.val) # 假设会用到self.val,所以这里有,根据实际情况,可有可无
def func2(self):
print('步骤1.....', self.val) # 假设会用到self.val,所以这里有,根据实际情况,可有可无
# 重写run方法 作为我们启动一个子进程的时候要执行的代码
def run(self):
self.func1()
self.func2()
if __name__ == '__main__':
p = MyProcess(2)
p.start()
2. 小练习:求1000以内的质数和
"""
求100000以内的质数和 记录下用的时间
使用4个进程 将100000分成4份 分别算当中的质数 记录下用的时间
"""
import time
from multiprocessing import Process
# 判断一个数 是不是质数:质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
def is_prime(n):
if n < 1:
return False
for i in range(2, n): # range(2, 5) 2, 3, 4
if n % i == 0: # 5 % 2 5 % 3 5 % 4
return False
return True
def no_process():
res = []
for i in range(1, 100001):
if is_prime(i): # 判断是否为质数
res.append(i)
print(sum(res)) # 求和
# 此处用来计算运行的时间
# s = time.time()
# no_process()
# print(time.time()-s) # 26.844652891159058
class Prime(Process):
def __init__(self, begin, end):
self.begin = begin
self.end = end
super().__init__()
def run(self) -> None: # 代表这个方法返回值是空,我们不用管
res = []
for i in range(self.begin, self.end):
if is_prime(i):
res.append(i)
print(sum(res))
# 使用4个进程 将100000分成4份 分别算当中的质数 记录下用的时间
def process_4():
jobs = []
for i in range(1, 100001, 25000): # 100000分成4份,一份25000
p = Prime(i, i+25000)
jobs.append(p)
p.start()
for job in jobs:
job.join() # 等进程全部执行完
if __name__ == '__main__':
s = time.time()
process_4()
print(time.time() - s)
时间
def process_4():
jobs = []
for i in range(1, 100001, 25000): # 100000分成4份,一份25000
p = Prime(i, i+25000)
jobs.append§
p.start()
for job in jobs:
job.join() # 等进程全部执行完
if name == ‘main’:
s = time.time()
process_4()
print(time.time() - s)
到1小时8分