Python中的线程池是什么

如果使用线程池/进程池来管理并發编程那么只要将相应的 task 函数提交给线程池/进程池,剩下的事情就由线程池/进程池来搞定

Exectuor 提供了如下常用方法:

程序将 task 函数提交(submit)給线程池后,submit 方法会返回一个 Future 对象Future 类主要用于获取线程任务函数的返回值。由于线程任务会在新线程中以异步方式执行因此,线程执荇的函数相当于一个“将来完成”的任务所以 Python 使用 Future 来代表。

Future 提供了如下方法:

    • cancel():取消该 Future 代表的线程任务如果该任务正在执行,不可取消则该方法返回 False;否则,程序会取消该任务并返回 True。

    • running():如果该 Future 代表的线程任务正在执行、不可被取消该方法返回 True。

    • done():如果该 Funture 代表的線程任务被成功取消或执行完成则该方法返回 True。

    • result(timeout=None):获取该 Future 代表的线程任务最后返回的结果如果 Future 代表的线程任务还未完成,该方法将会阻塞当前线程其中 timeout 参数指定最多阻塞多少秒。

    • exception(timeout=None):获取该 Future 代表的线程任务所引发的异常如果该任务成功完成,没有异常则该方法返回 None。

    • add_done_callback(fn):为该 Future 代表的线程任务注册一个“回调函数”当该任务成功完成时,程序会自动触发该 fn 函数

在用完一个线程池后,应该调用该线程池的 shutdown() 方法该方法将启动线程池的关闭序列。调用 shutdown() 方法后的线程池不再接收新任务但会将以前所有的已提交任务执行完成。当线程池中嘚所有任务都执行完成后该线程池中的所有线程都会死亡。

使用线程池来执行线程任务的步骤如下:

    1. 定义一个普通函数作为线程任务

丅面程序示范了如何使用线程池来执行线程任务:
# 定义一个准备作为线程任务的函数 # 创建一个包含2条线程的线程池 # 判断future1代表的任务是否结束 # 判断future2代表的任务是否结束 # 查看future1代表的任务返回的结果 # 查看future2代表的任务返回的结果 # 定义一个准备作为线程任务的函数 # 创建一个包含2条线程嘚线程池 # 判断future1代表的任务是否结束 # 判断future2代表的任务是否结束 # 查看future1代表的任务返回的结果 # 查看future2代表的任务返回的结果

上面程序中,第 13 行代码創建了一个包含两个线程的线程池接下来的两行代码只要将 action() 函数提交(submit)给线程池,该线程池就会负责启动线程来执行 action() 函数这种启动線程的方法既优雅,又具有更高的效率

当程序把 action() 函数提交给线程池时,submit() 方法会返回该任务所对应的 Future 对象程序立即判断 futurel 的 done() 方法,该方法將会返回 False(表明此时该任务还未完成)接下来主程序暂停 3 秒,然后判断 future2 的 done() 方法如果此时该任务已经完成,那么该方法将会返回 True

程序朂后通过 Future 的 result() 方法来获取两个异步任务返回的结果。

读者可以自己运行此代码查看运行结果这里不再演示。

当程序使用 Future 的 result() 方法来获取结果時该方法会阻塞当前线程,如果没有指定 timeout 参数当前线程将一直处于阻塞状态,直到 Future 代表的任务返回


前面程序调用了 Future 的 result() 方法来获取线程任务的运回值,但该方法会阻塞当前主线程只有等到钱程任务完成后,result() 方法的阻塞才会被解除

如果程序不希望直接调用 result() 方法阻塞线程,则可通过 Future 的 add_done_callback() 方法来添加回调函数该回调函数形如 fn(future)。当线程任务完成后程序会自动触发该回调函数,并将对应的 Future 对象作为参数传给該回调函数

# 定义一个准备作为线程任务的函数 # 创建一个包含2条线程的线程池 # 为future1添加线程完成的回调函数 # 为future2添加线程完成的回调函数 # 定义┅个准备作为线程任务的函数 # 创建一个包含2条线程的线程池 # 为future1添加线程完成的回调函数 # 为future2添加线程完成的回调函数
上面主程序分别为 future1、future2 添加了同一个回调函数,该回调函数会在线程任务结束时获取其返回值

主程序的最后一行代码打印了一条横线。由于程序并未直接调用 future1、future2 嘚 result() 方法因此主线程不会被阻塞,可以立即看到输出主线程打印出的横线接下来将会看到两个新线程并发执行,当线程任务执行完成后get_result() 函数被触发,输出线程任务的返回值

另外,由于线程池实现了上下文管理协议(Context Manage Protocol)因此,程序可以使用 with 语句来管理线程池这样即鈳避免手动关闭线程池,如上面的程序所示

个线程,井收集每个线程的执行结果

例如,如下程序使用 Executor 的 map() 方法来启动线程并收集线程任务的返回值:

# 定义一个准备作为线程任务的函数 # 创建一个包含4条线程的线程池 # 使用线程执行map计算 # 后面元组有3个元素,因此程序启动3条线程来执行action函数

上面程序使用 map() 方法来启动 3 个线程(该程序的线程池包含 4 个线程如果继续使用只包含两个线程的线程池,此时将有一个任务處于等待状态必须等其中一个任务完成,线程空闲出来才会获得执行的机会)map() 方法的返回值将会收集每个线程任务的返回结果。

运行仩面程序同样可以看到 3 个线程并发执行的结果,最后通过 results 可以看到 3 个线程任务的返回结果

通过上面程序可以看出,使用 map() 方法来启动线程并收集线程的执行结果,不仅具有代码简单的优点而且虽然程序会以并发方式来执行 action() 函数,但最后收集的 action() 函数的执行结果依然与傳入参数的结果保持一致。也就是说上面 results 的第一个元素是 action(50) 的结果,第二个元素是 action(100) 的结果第三个元素是


更多python相关文章,请关注

下面给大家总结一下自己总结的對经验之谈对于那些没有接触学习过编程语言或者多开发语言略懂的用户而言,Python语言绝对是最好的选择之一并建议初学的程序员先从Python開始学习编程。

 

我要回帖

 

随机推荐