2016-08-02 46 views
4

Mein Code ist wie unten,Was bewirkt ein Aufruf von queue.join() im Haupt-Thread auf Nicht-Haupt-Threads?

import time, queue, threading 

def washer(dishes, dish_queue): 
    for dish in dishes: 
     print ("Washing", dish) 
     time.sleep(1) 
     dish_queue.put(dish) 

def dryer(dish_queue): 
    while True: 
     dish = dish_queue.get() 
     print("Drying", dish) 
     time.sleep(2) 
     dish_queue.task_done() 
     print('dryer') 

dish_queue = queue.Queue() 
for n in range(2): 
    dryer_thread = threading.Thread(target=dryer, args=(dish_queue,)) 
    dryer_thread.start() 

dishes = ['salad', 'bread', 'entree', 'desert'] 
washer(dishes, dish_queue) 
dish_queue.join() 

Von meinem Verständnis in der Warteschlange Modul Dokumentation, dish_queue.join() den Haupt-Thread, bis die Anzahl der unerledigten Aufgaben blockieren (hier ist nicht getrocknetes Geschirr) auf 0 zurück. Aber ich frage mich, was mit dem 2 dryer_thread passiert ist.

Ich habe festgestellt, dass, wenn ich die Funktion dryer auf einem leeren dish_queue im Hauptprogramm ausführen, das Programm blockiert ist (BTW, ist dies der sogenannte Block von Dish_queue.get()?). Also, wenn dish_queue.join() den Haupt-Thread freigibt, die 2 dryer_thread auch entsperren und den Speicher freigeben? Was bedeutet Block bedeuten sowieso in der Warteschlange doc?

Antwort

1

Die kurze Antwort auf Ihre Hauptfrage ist nichts.

Für eine längere Antwort, hier sind zwei Gleichzeitigkeit graphischen Darstellungen, eine ohne Wartezeit: enter image description here

Und eins mit: enter image description here

Wie Sie am Anfang sehen können sowohl die beiden Trockner Gewinde sind in eine Sperre, die, wie Sie richtig verstanden haben, get() Block ist. Jetzt, im ersten Fall, endet das Hauptgewinde nach Beendigung der Waschfunktion. Beim Hinzufügen der dish_queue.join() wartet der Haupt-Thread auf die Dish-Warteschlange, um alle Aufgaben zu beenden. Wenn Sie also sagen, dass join() den Hauptthread freigibt, heißt das, dass er seinen eigenen Block entfernt. Wie Sie sehen können, sind die anderen Threads davon nicht betroffen und bleiben blockiert.

Was Block ist, ist es, wenn ein Thread oder ein Prozess auf Eingaben von außerhalb des Threads wartet oder in diesem Fall auf das Element in der Warteschlange wartet. Falls Sie die anderen Threads stoppen möchten, müssen Sie entweder eine Zeitüberschreitung zu get() hinzufügen (die eine Ausnahme auslöst und den Thread beendet), oder sie nach der dish_queue.join() beenden.

+0

Neben dem Festlegen eines Zeitlimits, was schlagen Sie vor, um die anderen Threads zu beenden? Ich bin mir nicht sicher, ob andere Threads als Daemon arbeiten. Wenn ich meinen Code nicht ändere und sie einfach blockiere, verbrauchen sie wirklich meinen Speicher? – Nicholas

+0

BTW, welchen Parallelitätsmonitor benutzen Sie? Es ist klassisch! – Nicholas

+0

Im Allgemeinen ist ein Thread mit einem Block der gleiche wie ein schlafender Thread. Es wird seinen Speicher nicht freigeben, aber es werden auch keine zusätzlichen Ressourcen verbraucht. Es hängt also davon ab, ob Sie den Thread in Zukunft benötigen. Zu beachten ist, dass die Threads so lange vorhanden sind, wie der Hauptthread aktiv ist. Daher sollten Sie keine neuen Threads öffnen und stattdessen neue Elemente zur vorhandenen Warteschlange hinzufügen. Ich verwende pyCharm, das ist eine großartige allround IDE. – Aruj