1.基础概念
将计算机的cpu理解为工厂,但是假定这个工厂的电力有限,一次只能给一个车间供电。
1)进程:看做工厂的一个车间,拥有独立内存。代表cpu所能处理的单个任务,任一时刻,cpu总是运行一个进程,其他进程处于非运行状态。能够运行的多进程的数量一般等于cpu的核数。
2)线程:看做工厂车间的一个工人,可以共享内存,他们可以协同完成一个任务。
以dell latitude 7430为例,他的设备参数为10核 12线程。线程为什么也能用cpu来定义?
2. 为什么要使用多进程?
对比程序:计算8的20次方,sleep 2 秒。
1)使用传统方式完成计算
# 单进程示例程序
import time
import os
def long_time_task():
print('当前进程:{}'.format(os.getpid())) #得到当前的进程号
time.sleep(2)
print("结果:{}".format(8**20))
if __name__=="__main__":
print('当前母进程:{}'.format(os.getpid()))
start=time.time()
for i in range(2):
long_time_task()
end=time.time()
print("use time{} seconds".format((end-start)))
# 知道了如何得到当前的进程号
# 知道了一段简单的程序如何计算(统计)时间
'''
out:
当前母进程:266156
当前进程:266156
结果:1152921504606846976
当前进程:266156
结果:1152921504606846976
use time4.004450559616089 seconds
'''
2)使用两个进程完成相同的计算
# 多进程显示示例 创建两个进程p1 p2进行并行计算
from multiprocessing import Process
import os
import time
def long_time_task(i):
print('子进程:{}-任务{}'.format(os.getpid(),i))
time.sleep(2)
print('结果:{}'.format(8**20))
if __name__=="__main__":
print('当前母进程:{}'.format(os.getpid()))
start=time.time()
# 创建两个进程
p1=Process(target=long_time_task,args=(1,))
p2=Process(target=long_time_task,args=(2,))
print('等待所有子进程完成。')
p1.start() # 启动子进程
p2.start()
p1.join() #让该进程阻塞,直到调用join的进程终止 这个代码的目的是为了记录进程阻塞的时间 便于时间统计
p2.join()
end=time.time()
print('总共用时{}秒'.format((end-start)))
# 两个进程是完成相同的事情
# 母进程与子进程的关系:母进程是为了调用子进程?
'''
out:
当前母进程:266156
等待所有子进程完成。
子进程:268112-任务1
子进程:268115-任务2
结果:1152921504606846976
结果:1152921504606846976
总共用时2.0291872024536133秒
'''
3. 多进程进阶
3.1 Pool类
满足当进程数量很多时,创建多个进程以提高cpu利用率的需求(管理系统中并发进程的数量)。具体来说,pool类会统一管理进程的数量(提供指定数量的进程供用户使用),当进程池还没有满,用户有需求时,进程池就会创建相应的进程。若进程池满了,用户有需求时,进程池就会告诉用户先等待。
3.2 Queue队列
用于帮助进程间进行数据通讯
from multiprocessing import Process,Queue
import os,time,random
# 用于写数据的进程
def write(q):
print('Process to write:{}'.format(os.getgid())) # 将可变变量输入到字符串中
for value in ['A','B','C']:
print('Put %s to Queue...'%value) # 占位符 也是用来将变量输入到字符串中
q.put(value) # 将数据放入队列
time.sleep(random.random())
# 用于读数据的进程
def read(q):
print('Process to read:{}'.format(os.getpid()))
while True:
value=q.get(True) # 从队列中取出想要的数据 只能强行终止
print('Get %s from queue'% value)
# 主进程调用程序:创建队列 创建读写进程 调用读写进程
if __name__ =="__main__":
# 父进程创建Queue 传给各个子进程
q=Queue()
pw=Process(target=write,args=(q,))
pr=Process(target=read,args=(q,))
pw.start()
pr.start()
pw.join() # 阻塞 等待程序完成
pr.terminate() # 只能强行终止??
'''
out:
Process to write:1004
Put A to Queue...
Process to read:268281
Get A from queue
Put B to Queue...
Get B from queue
Put C to Queue...
Get C from queue
'''