进程池与线程池(掌握)
先回顾之前TCP服务端实现并发的效果是怎么玩的
每来一个人就开设一个进程或者线程去处理
无论是开设进程也好还是开设线程也好是不是都需要消耗资源
只不过开设线程的消耗比开设进程的稍微小一点而已
我们是不可能做到无限制的开设进程和线程的因为计算机硬件的资源更不上
硬件的开发速度远远赶不上软件呐
我们的宗旨应该是在保证计算机硬件能够正常工作的情况下最大限度的利用它
#池的概念
'''
什么是池?
池是用来保证计算机硬件安全的情况下最大限度的利用计算机
它降低了程序的运行效率但是保证了计算机硬件的安全从而让你写的程序能够正常运行
'''
ThreadPoolExecutor = 线程池
ProcessPoolExecutor = 进程池
concurrent.futures 模块
# concurrent.futures模块的基础是Exectuor,Executor是一个抽象类,它不能被直接使用。
但是它提供的两个子类ThreadPoolExecutor和ProcessPoolExecutor却是非常有用,
顾名思义两者分别被用来创建线程池和进程池的代码。我们可以将相应的tasks直接放入线程池/进程池,
不需要维护Queue来操心死锁的问题,线程池/进程池会自动帮我们调度。
# Future这个概念相信有java和nodejs下编程经验的朋友肯定不陌生了,
你可以把它理解为一个在未来完成的操作,这是异步编程的基础,传统编程模式下比如我们操作queue.get的时候,
在等待返回结果之前会产生阻塞,cpu不能让出来做其他事情,而Future的引入帮助我们在等待的这段时间可以完成其他的操作
代码演练
import os
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time
pool = ThreadPoolExecutor(5) #设定线程池里固定有个5个线程
# 括号内可以传数字 不传的话 默认当前计算机CPU个数五倍的线程
pool = ProcessPoolExecutor()
'''
池子造出来后,里面固定存在5个线程
这5个线程不会出现重复创建和销毁的过程
池子的使用非常简单
你只需要把需要做的任务往池子里提交,自动会有人来服务你
'''
def task(n):
print(n,os.getpid())
time.sleep(2)
return n**n
'''
任务提交的方式:
同步:提交任务后原地等待任务的返回结果,期间不做事
异步:提交任务后原地不等待任务的返回结果,继续往下执行
pool.submit(task,1) #submit异步提交 朝池子里提交任务
'''
if __name__ == '__main__':
t_list=[]
for i in range(20): #朝池子里提交20个任务
res = pool.submit(task,i)
t_list.append(res)
# 等待线程池中所有任务执行完毕后再继续往下执行
pool.shutdown() # 关闭线程池
for t in t_list:
print('>>>:',t.result())