百度百科
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。
进程,首先理解进程的概念,假如我们的电脑内存大小是一定的,要开启多个软件,内存的占用就会越来越大,计算机有自己的处理方式。例如时间片轮转,优先级调度等。如果内存当前被占用大部分的空间,开启的软件过多,其他软件也要得到计算机的内存空间,这时候内存就会轮番调度。这个时间间隔是非常短暂的给人的感觉就是多个软件在一起执行。
Python中创建多进程。Python的OS模块封装了常见的系统调用,多进程的调用就是fork,可以使用python创建多进程。
import os
pid = os.fork() # 返回值等于0时,子进程
print(pid)
if pid>0:
print("---父进程--%d-"%os.getpid())
else:
print("---子进程---%d-%d-"%(os.getpid(),os.getppid()))
注意,在win系统中,没有fork这个系统调用,那么如何在win系统中开启多进程呢?
第二种创建进程的方式,是通过Multiprocessing模块中的Process类,创建Process对象,通过对象参数target=“需要执行的子进程”
from multiprocessing import Process
import time
def test(pid:str):
while True:
print("---%s---" % pid)
time.sleep(1)
p1 = Process(target=test,args=('p1',)) # target参数需要执行的子进程
p2 = Process(target=test,args=('p2',)) # target参数需要执行的子进程
p1.start() # 让这个进程开始执行test函数里的代码
p2.start()
启动程序后,打印语句交替执行
注:与fork的不同点;fork不是跨平台的,在win系统中不能使用,而在win系统中使用Process对象来调用子进程需要执行的方法。通过start开启子进程;在fork中,主进程不会等待子进程的结束,而结束主进程,在Process开启的子进程中,会等待所有的子进程结束后,才会结束主进程。
创建子类,继承父类(Process),重写Run方法
,实例化子类对象时,通过对象start开启子进程,子进程所执行的内容,就是在重写的run
方法中的内容。在.start()
方法时,会自动调用run
方法。
from multiprocessing import Process
import time
class MyNewProcess(Process):
def run(self): # 重写run方法
while True:
print("---1----")
time.sleep(1)
p = MyNewProcess()
p.start() # 开启进程
while True:
print("---main----")
time.sleep(1)
继承父类的这种方式,底层的实现其实就是Process创建的方式。
当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态生成多个进程。
但是如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以使用multiprocessing模块中的Pool方法。
初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool时,如果池还没有满,那么就会创建一个新的进程来执行该请求;但如果池中的进程数已满,那么该请求就会等待,直到池中有进程结束,才会创建新的进程执行。
Pool方法即进程池,需要说明有几个进程同时运行。在使用apply_async方法时第一个参数是函数名,第二个参数需要输入一个元组。在示例代码中,进程池同时允许三个进程运行,另外七个进程排队等候,当第一批的三个进程执行完后,第二批的三个再执行。所以进程池相当于起到了缓冲的作用。
实际上,在进程池的方式中,父进程基本上只需要等待子进程执行(使用pool.join()进行等待),任务都是交给子进程执行的。
from multiprocessing import Pool
import time,os
# 非阻塞式进程
from random import random
def task(task_name):
print('开始做任务啦!',task_name)
start = time.time()
# 使用sleep
time.sleep(random() * 2)
end = time.time()
print('完成任务:{}! 耗时:{} ,进程ID:{}'.format(task_name,(end-start),os.getpid()))
# 容器
container = []
def callback_func(n):
container.append(n)
if __name__ == '__main__':
pool = Pool(5)
tasks = ['听音乐','看电影','读书','看报','玩游戏','打篮球','弹钢琴']
for t in tasks:
pool.apply_async(task,args=(t,))
pool.close() # 关闭进程池,不允许继续添加进程
pool.join() # 等待进程池中的所有进程结束
print('------'*10)
for c in container:
print(c)
print('over!!!!!!!!!!')
输出结果:
开始做任务啦! 听音乐
开始做任务啦! 看电影
开始做任务啦! 读书
开始做任务啦! 看报
开始做任务啦! 玩游戏
完成任务:看报! 耗时:0.569094181060791 ,进程ID:21451
开始做任务啦! 打篮球
完成任务:看电影! 耗时:0.6920769214630127 ,进程ID:21449
开始做任务啦! 弹钢琴
完成任务:玩游戏! 耗时:0.9521348476409912 ,进程ID:21452
完成任务:打篮球! 耗时:0.6299769878387451 ,进程ID:21451
完成任务:听音乐! 耗时:1.453145980834961 ,进程ID:21448
完成任务:读书! 耗时:1.7922098636627197 ,进程ID:21450
完成任务:弹钢琴! 耗时:1.6441609859466553 ,进程ID:21449
------------------------------------------------------------
over!!!!!!!!!!