线程返回值

在 POSIX 标准中,pthread_join(3) 可以接收另一线程 pthread_exit(3) 指定的返回值。然而在 Python 中,线程标准库 threadingThread 对象的 join() 方法,却不能接收线程函数的返回值。

本人猜测,部分原因由于线程本身没有像进程一样的父子关系,即任何线程都可以调用某个 Thread 对象的 join() 方法,且可以调用多次。相反,POSIX 只允许对线程调用 1 次 pthread_join(3) 方法。

问题是我们有时确实需要取得线程的返回值,例如使用线程在后台执行耗时较长的任务,怎么办?其中一种解决办法是使用全局变量,线程在执行的过程中更新全局变量的值,当调用 join() 方法确定线程结束后,我们可以认为全局变量是线程的执行结果。这种方法完全绕开了返回值的问题,但存在几个问题:

  • 有时函数是第三方实现的,不受管理
  • 强化了代码间的耦合,不利于代码的维护
  • 有多个线程时,需要给每个线程分配一个全局变量,通常使用全局的 listdict

本文讨论的主角是 Python 3.2 引入的 concurrent.futures 标准库,其中的 ThreadPoolExecutor 较好地解决了上述的问题。当我们对 Executor 提交函数任务后,将返回一个 Future 对象。我们可以先完成其他任务,等需要的时候再调用其 result() 方法异步获取结果。下面是一个小例子:

import concurrent.futures

executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)
future = executor.submit(func)
# Do some other work
print(future.result())

除了线程池模型的 ThreadPoolExecutor 外,模块中还有按照进程池模型设计的 ProcessPoolExecutor,使用方式类似。模块中还有 wait() 函数,它可以同时等待多个 Future 对象的结果。

Advertisements