在不阻塞的情况下使用 ThreadPoolExecutor

4 python multithreading threadpoolexecutor

作为对这个问题的跟进,我有一个简单的脚本,它开始threadpoolexecutor读取json文件。这样做时,我想使用for循环从 1 到 9 计数。出于某种原因,即使我使用executor.shutdown(wait=False)它仍然阻塞并等待read_employees方法执行。

根据文档

如果 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()
Run Code Online (Sandbox Code Playgroud)

如果我要这样做:

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()
Run Code Online (Sandbox Code Playgroud)

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

1
2
3
4
5
6
7
8
9
ams@yourcompanyname.com
bcs@yourcompanyname.com
Run Code Online (Sandbox Code Playgroud)

如何使用threadpoolexecutor无阻塞实现相同的输出?

Mic*_*dam 10

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

在这种情况下,ThreadPoolExecutor是上下文管理器。ThreadPoolExecutor是 的子类Executor。所以通过引用Executor的类定义,我们可以看到__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)
Run Code Online (Sandbox Code Playgroud)


Pio*_*kin 0

可能是由于这个小片段:

“如果使用该语句,则可以避免必须显式调用此方法with,这将关闭Executor(等待就像Executor.shutdown()使用waitset to调用一样True)”

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