2013-03-02 13 views
12

Sono nuovo di python (io vengo da PHP), ho letto i tutorial e provare cose per un paio di giorni, ma non riesco a capire questo esempio di coda (http://docs.python.org/2/library/queue.html)discussioni Python e la fila esempio

def worker(): 
    while True: 
     item = q.get() 
     do_work(item) 
     q.task_done() 

q = Queue() 
for i in range(num_worker_threads): 
    t = Thread(target=worker) 
    t.daemon = True 
    t.start() 

for item in source(): 
    q.put(item) 

q.join()  # block until all tasks are done 

La cosa che non capisco è come il thread di lavoro completa ed esiste. Ho letto i blocchi q.get() fino a quando un elemento non è disponibile, quindi se tutti gli elementi sono elaborati e nessuno è lasciato in coda perché q.get() non blocca per sempre?

risposta

9

I thread non escono normalmente in questo codice (sono infatti bloccati quando la coda è vuota). Il programma non li aspetta perché sono daemon threads.

Il programma non esce immediatamente e non si blocca per sempre a causa delle chiamate q.join e q.task_done.

Il conteggio delle attività non completate aumenta ogni volta che un articolo viene aggiunto alla coda. Il conteggio diminuisce ogni volta che un thread utente chiama task_done() per indicare che l'elemento è stato recuperato e tutti i lavori su di esso sono completi. Quando il conteggio delle attività non terminate scende a zero, join() sblocca e il programma esiste senza attendere i thread del daemon.

-3

Ho avuto lo stesso problema. Quando tutti i thread sono stati completati, ho visto "thread dormienti" nella lista dei processi (usa top -H -p <pid> dove <pid> è id processo da ps aux | grep python con il tuo script).

Ho risolto questo problema sostituendo "infinito loop" while True a while not q.empty():.

Ha risolto il problema con "thread dormienti".

def worker(): 
    while not q.empty(): 
     item = q.get() 
     do_work(item) 
     q.task_done() 

q = Queue() 
for i in range(num_worker_threads): 
    t = Thread(target=worker) 
    t.daemon = True 
    t.start() 

for item in source(): 
    q.put(item) 

q.join()  # block until all tasks are done 
+0

Questa soluzione è piuttosto rischiosa. Se i thread worker sono veloci, testeranno 'q.empty()' prima che tutti gli elementi siano stati aggiunti alla coda, e quindi escono prima che abbiano fatto qualcosa. Allo stesso modo, se c'è un singolo elemento lasciato in coda e due thread testano 'q.empty()' contemporaneamente, entrambi continueranno ma uno otterrà un elemento fuori dalla coda mentre l'altro bloccherà a 'q.get() '. –