【问题标题】:Using ThreadPoolExecutor without Blocking使用 ThreadPoolExecutor 而不阻塞
【发布时间】:2017-11-14 15:41:34
【问题描述】:

作为this question 的后续行动,我有一个简单的脚本,它启动threadpoolexecutor 以读取json 文件。这样做时,我想使用 for 循环将其从 1 计数到 9。出于某种原因,即使我使用了executor.shutdown(wait=False),它仍然会阻塞并等待read_employees 方法执行。

根据documentation

如果 wait 为 False,则此方法将立即返回,并且当所有未决的期货执行完毕后,与执行器关联的资源将被释放

import concurrent.futures
import json
import time


def read_employees(read_file):
    with open(read_file) as f_obj:
        employees = json.load(f_obj)

    for emp in employees:
        print(emp)
        time.sleep(3)


def start_thread():
    filename = 'employee.json'
    with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
        executor.submit(read_employees, filename)
        executor.shutdown(wait=False)

def print_number():
    for num in range(1,10):
        time.sleep(2)
        print(num)


start_thread()
print_number()

如果我这样做:

def read_employees(read_file):
    with open(read_file) as f_obj:
        employees = json.load(f_obj)

    for emp in employees:
        time.sleep(5)
        print(emp)


def print_number():
    for num in range(1,10):
        print(num)


filename = 'employee.json'
empThread = threading.Thread(target=read_employees, args=(filename,))
empThread.start()

print_number()

先从 1 数到 9,然后打印出员工,延迟是因为在阅读员工时睡觉。像这样:

1
2
3
4
5
6
7
8
9
ams@yourcompanyname.com
bcs@yourcompanyname.com

如何在不阻塞的情况下使用threadpoolexecutor 实现相同的输出?

【问题讨论】:

    标签: python multithreading threadpoolexecutor


    【解决方案1】:

    我建议您不要使用with 语句。通过调用context manager__exit__ 方法来关闭with 语句。上下文管理器是任何实现__enter____exit__ 方法的类。因此,在 with 语句中运行所有内容后,它会在传入的上下文管理器上调用 __exit__

    在这种情况下,ThreadPoolExecutor 是一个上下文管理器。 ThreadPoolExecutorExecutor 的子类。所以通过引用Executor's class definition,我们看到在它的__exit__方法中它调用了self.shutdown(wait=True)

    self.shutdown(wait=True) 的调用是问题所在。如果您遵循上下文管理器的工作方式,由于 self.shutdown(wait=False) 是您的 with 语句中的最后一件事,因此将在之后直接调用 __exit__。这意味着将调用self.shutdown(wait=True)。所以这就是阻碍你的原因。

    您有两种选择来解决此问题。第一个是继承ThreadPoolExecutor,重写__exit__方法。

    第二种选择是这样做:

    def start_thread():
        filename = 'employee.json'
        executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)
        executor.submit(read_employees, filename)
        executor.shutdown(wait=False)
    

    【讨论】:

      【解决方案2】:

      可能是因为这个小sn-p:

      “如果你使用with语句,你可以避免显式调用这个方法,这将关闭Executor(等待Executor.shutdown()被调用,wait设置为True)”

      https://docs.python.org/3/library/concurrent.futures.html

      【讨论】:

      • 这就是为什么我将wait 设置为False,但它仍然像阻塞一样输出。
      猜你喜欢
      • 1970-01-01
      • 2011-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多