2017-11-14 10 views
0
Blocking

Als Follow-up auf this question, ich habe eine triviale Skript, das ein threadpoolexecutor beginnt in einer json Datei zu lesen. Dabei will ich von 1 bis 9 mit einer for Schleife zählen. Aus irgendeinem Grund, obwohl ich executor.shutdown(wait=False) verwendet, blockiert es immer noch und wartet auf die Ausführung der read_employees-Methode.ThreadPoolExecutor Verwendung ohne

bis Nach der documentation:

Wenn Wartezeit ist falsch, dann wird diese Methode sofort zurück, und die mit dem Testamentsvollstrecker zugehörigen Ressourcen freigegeben werden, wenn alle ausstehenden Futures getan ausführen

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() 

Wenn ich dies tun würde:

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() 

Es zählt zuerst von 1 bis 9 und druckt dann die Mitarbeiter aus, die Verspätung ist wegen des Schlafes beim Lesen der Mitarbeiter. Wie so:

1 
2 
3 
4 
5 
6 
7 
8 
9 
[email protected] 
[email protected] 

Wie erreiche ich die gleiche Leistung mit dem threadpoolexecutor, ohne zu blockieren?

Antwort

0

Wahrscheinlich aufgrund dieser kleine Ausschnitt:

„Sie vermeiden können mit dieser Methode explizit aufrufen, wenn Sie die with Anweisung verwenden, das wird Abschaltung der Executor (Warte als ob Executor.shutdown() mit wait Satz True genannt wurden) "

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

+0

diesem Grund habe ich die 'wait' auf' false' gesetzt, aber es gibt immer noch, als ob es blockiert. –

1

ich würde empfehlen, dass Sie keine with Anweisung verwenden. Eine with Anweisung wird geschlossen, indem die __exit__ Methode einer context manager aufgerufen wird. Ein Kontextmanager ist jede Klasse, die eine Methode __enter__ und __exit__ implementiert. Nachdem alles in einer with -Anweisung ausgeführt wird, ruft es __exit__ auf dem Kontextmanager auf, der übergeben wurde.

In diesem Fall ist ThreadPoolExecutor ein Kontextmanager. ThreadPoolExecutor ist eine Unterklasse von Executor. So, indem wir auf Executor's class definition verweisen, sehen wir, dass in seiner __exit__ Methode es self.shutdown(wait=True) ruft.

Dieser Anruf an self.shutdown(wait=True) ist das Problem. Wenn Sie der Funktionsweise des Kontextmanagers folgen, wird self.shutdown(wait=False) das letzte in Ihrer with-Anweisung sein, __exit__ wird direkt danach aufgerufen. Und das bedeutet, dass self.shutdown(wait=True) aufgerufen wird. Das ist es also, was dich blockiert.

Sie haben zwei Möglichkeiten, dies zu beheben. Die erste ist die Unterklasse ThreadPoolExecutor und die __exit__ Methode neu schreiben.

Die zweite Option ist, so etwas zu tun:

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