十六.线程池概念
1.什么是线程池
与进程池类似, 线程池是在系统启动时就先创建大量空闲的线程, 程序提交一个任务给线程池, 线程池便会调用一个线程来执行该任务, 当任务运行完毕后, 该线程并不会关闭, 而是返回到线程池中再次变为空闲状态等待下一个提交的任务,
2.为什么使用线程池
虽说线程的启动相比较于进程开销非常小, 但毕竟也是需要向操作系统发起调用, 我们使用线程在一些情况下能更好的提升性能, 尤其是程序中有大量生命期短暂的线程时, 使用线程池最为合适了
3.线程池的作用
使用线程池可以精确控制操作系统中并发线程的数量, 如果操作系统中有大量的并发线程, 并且没有限制数量, 那么就会导致操作系统的性能急剧下降, 甚至导致程序的崩溃, 而线程池可以通过控制最大线程数来解决该问题
十七.线程池的使用 (concurrent.futures 模块)
1.concurrent.futures 模块
concurrent.futures模块是Python标准库模块, 它提供了Executor类, 而 Executor又提供了两个子类,即ThreadPoolExecutor和 ProcessPoolExecutor,其中ThreadPoolExecutor用于创建线程池,而ProcessPoolExecutor用于创建进程池, 也可以把这两个子类看作高度封装的异步调用接口
2.常用方法
方法 | 说明 |
---|---|
submit(fn, *args, **kwargs) | 将任务fn提交给进程池(异步提交), 后面的是参数 |
map(func, *iterables, timeout=None, chunksize=1) | 类似于map函数, 升级版本开启多进程以异步的方式来对可迭代对象进行map处理,也类似于取代for循环submit的操作 |
shutdown(wait=True) | 关闭线程池, (下面进行详解) |
result(timeout=None) | 获得该线程任务的结果, 如果任务未执行完会进行阻塞, 参数为超时时间 |
add_done_callback(fn) | 为该线程设置回调, 当该线程完成任务时, 程序会自动触发fn函数 |
-
shutdown(wait=True)
详解:
相当于进程池的**pool.close( ) + pool.join( )**操作
wait=True, 等待池内所有任务执行完毕回收完资源后才继续
wait=False, 立即返回, 并不会等待池内的任务执行完毕
但不管wait参数为何值,整个程序都会等到所有任务执行完毕
submit和map必须在shutdown之前
注意 : 在用完一个线程池后,应该调用该线程池的**shutdown( )方法,该方法将启动线程池的关闭序列, 调用shutdown( )**方法后的线程池不再接收新任务, 但会将以前所有的已提交任务执行完成, 当线程池中的所有任务都执行完成后, 该线程池中的所有线程都会死亡
3.使用ThreadPoolExecutor线程池启动线程任务步骤
- 使用ThreadPoolExecutor类创建一个线程池对象
- 创建一个任务task (普通函数)
- 调用线程池对象的**submit( )**方法来提交任务
- 当没有任务的时候调用**shutdown( )**方法来关闭进程池
4.ThreadPoolExecutor使用示例
**ps