1.进程池1
# 为什么会有进程池的概念 # 开启多个进程会存在效率问题 # 每次开启进程,都需要为一个进程开启一个属于这个进程的内存空间 # 进程过多后,操作系统的调度切换也会变得复杂,保留的寄存器、堆栈、内存空间等等太多,耗费时间太多。 # 所以一般情况下,不会任意的开放多个进程 # 所以有了进程池的概念 # python中的进程池:在还没有启动你的程序之前,会先创建一个属于进程的池子,这个池子指定能存放多少个进程 # 当指定了多少个进程后,先将这些进程创建好。 # 比如指定了这个池子只能存放5个进程,则会先创建这5个进程。此时想起50个进程去处理一个问题时, # 不是同一时间开启了50个进程,而是让这50个进程排队,从池子里拿进程,一个进程从池子里拿一个进程,然后去处理这个任务, # 所以同一时间只能有5个进程找到了进程中的5个进程,拿到池子中的5个进程然后去处理问题,从池子中拿到的进程执行完毕后, # 将进程归还给池子,等待下一个进程来了后对池子的进程调度 # 好处是能节省内存的空间,50个进程同一时间只能调度池子中规定的进程数去处理任务,进程池中被调度后的进程执行完毕后继续归还到池子中,参与50进程剩下进程的调度 # 上面的概念是初学的概念,在说下概念:进程池,就是在池子中事先创建好了一些进程,比如是5个进程在池子中, # 此时当有20个任务要处理时,则会将20个任务排好队投入到进程池中,进程池中的一个进程只能对应一个任务,进程池中的进程拿到任务后则会去执行,执行完毕后,继续回到进程池中拿下一个进来的任务 # 进程池控制了能开启的进程数量,N个任务在同一时间只能被进程池规定的进程数执行 # 进程池和信号量的概念类似,信号量是一段代码同一时间只能被N个进程执行 # 进程池控制的是进程的数量,控制进程的数量就会控制住操作系统的调度时间、内存 # 更高级的进程池原理(python中没有这种更高级的进程池,不会弹性的伸缩) # 一个进程池被创建出来,有一个进程数的下线和一个进程数的上限n,m # 比如此时想处理一个时间段内向博客园访问的请求,博客园的访问请求在一些时间段内是少的,在一些时间段内是多的 # 所以正常情况下,比如进程池只有3个进程,到了访问高峰期时就可以加进程到进程池中,直到加到上限。当访问过了高峰期时,再将进程池中的数据量逐渐减少 # 何时使用进程何时使用进程池 # 当要处理的东西2个3个进程能处理时就用Process这种不是进程池的方法就行了 # 当要处理的超过5个时就可以用进程池Pool启进程了 import time from multiprocessing import Pool # 进程池模块 from multiprocessing import Process def func(n): for i in range(10): print(n + 1) if __name__ == '__main__': pool = Pool(5) # 创建一个进程池,参数就是进程池中存放的进程数,一般这个数是电脑CPU核心数+1 start = time.time() pool.map(func, range(100)) # 参数1是任务,参数2必须是一个可迭代的数据类型,表示100个任务.启动进程池处理这100个任务。阻塞等待任务处理完毕 t1 = time.time() - start print(t1) # 0.13662147521972656
2.进程池
# 其他进程池使用的方法 # # 进程池中执行任务,同步执行任务,一个任务执行完了,再执行另一个任务,称为同步提交任务的方式 # import time # import os # from multiprocessing import Pool # # def func(n): # print('start func %s' % n, os.getpid()) # time.sleep(1) # print('end func %s' % n, os.getpid()) # # if __name__ == '__main__': # pool = Pool(4) # for i in range(5): # pool.apply(func, args=(i, )) # 同步提交任务的方式,会等待子进程结束主进程代码才能继续执行 # 进程池中执行任务,异常执行任务,多个任务同时执行,称为异步提交任务的方式 import time import os from multiprocessing import Pool def func(n): print('start func %s' % n, os.getpid()) time.sleep(1) print('end func %s' % n, os.getpid()) if __name__ == '__main__': pool = Pool(4) for i in range(5): pool.apply_async(func, args=(i, )) # 异步提交任务的方式,不会阻塞在这里等待子进程结束 # 进程池执行5个任务同时异步执行,主进程代码继续执行,想要主进程感知到进程池中的任务执行结束了,需要先关闭掉进程池接收任务功能,然后在调用感知进程池中任务执行结束的方法 pool.close() # 关闭进程池接收任务,先让进程池不在接收任务,然后再调用下面的感知进程池中的任务执行结束的方法就可以阻塞等到进程池中的任务执行结束 pool.join() # 感知进程池中的任务执行结束 # 总结:进程池的创建 # pool = Pool(4) # pool.map(func, iterable) # 默认异步执行的任务,自带阻塞等待任务执行结束 # pool.apply(func, args=()) # 同步调用执行任务,一个任务执行完了才能执行另一个任务 # pool.apply_async(func, args=()) # 异步调用执行任务,完全异步,主进程需要手动关闭进程池的接收任务功能,才能阻塞感知到任务执行的结束