2016-11-22 37 views
0

Hier ist ein Beispielprogramm, das ich für Python-Thread-Sequenz zu testen liefPython threading Sequenz

import threading 
import time 
import logging 
import random 

logging.basicConfig(level=logging.DEBUG, 
     format = '%(asctime)s (%(threadName)-10s) %(message)s') 

def worker(): 
     t = threading.currentThread() 
     pause = random.randint(1,10) 
     logging.debug('sleeping %s', pause) 
     time.sleep(pause) 
     logging.debug('ending sleep') 
     return 

for i in range(3): 
     t = threading.Thread(target=worker,name='t%s'%i) 
     t.setDaemon(True) 
     t.start() 

main_thread = threading.currentThread() 
for t in threading.enumerate(): 
     if t is main_thread: 
       continue 
     logging.debug('joining %s', t.getName()) 
     t.join() 

Hier ist die Ausgabe eines Programmlaufs ist:

2016-11-22 12:59:12,052 (t0  ) sleeping 3 
2016-11-22 12:59:12,052 (t1  ) sleeping 3 
2016-11-22 12:59:12,052 (t2  ) sleeping 8 
2016-11-22 12:59:12,052 (MainThread) joining t0 
2016-11-22 12:59:15,055 (t0  ) ending sleep 
2016-11-22 12:59:15,056 (MainThread) joining t2 
2016-11-22 12:59:15,056 (t1  ) ending sleep 
2016-11-22 12:59:20,054 (t2  ) ending sleep 
2016-11-22 12:59:20,054 (MainThread) joining t1 

Hinweis des Verbindungs ​​Auftrag ist nicht konsistent entweder mit Listenreihenfolge oder mit der Timing-Reihenfolge. Die Verknüpfungsreihenfolge des Haupt-Threads sollte t0 -> t1 -> t2 Thread-Sequenz aufrufen, aber es ist -> t2 -> t1.

Was passiert hier?

+0

warum würden Sie das threading.enumerate() annehmen würde sie in der gleichen Reihenfolge zurückkehren sie erstellt? – bravosierra99

+0

Schritt 1 beim Lernen von Multithread: Ihre Threads werden in beliebiger Reihenfolge ausgeführt, und Sie können nichts dagegen tun. (Nun, das kannst du. Aber wenn du das tust, verlierst du alle und alle Gewinne, die du mit Multithreading erzielen wolltest.) – Delioth

Antwort

0

threading.enumerate() sagt nichts über die Reihenfolge, in der es die Threads auflistet. Mit Blick auf die Quelle werden Threads in zwei dict's namens _active und _limbo verfolgt. Wenn Sie aufzählen, listen Sie die Schlüssel dieser Wörterbücher auf, und ihre Reihenfolge ist nicht definiert.

Das Verbinden von Gewinden auf diese Weise ist riskant. Sie haben den Hauptthread berücksichtigt, aber was passiert, wenn Sie ein Modul importieren, das Hintergrundthreads für seine eigenen Zwecke verwendet? Stattdessen halten Sie Ihre eigene Liste

import threading 
import time 
import logging 
import random 

logging.basicConfig(level=logging.DEBUG, 
     format = '%(asctime)s (%(threadName)-10s) %(message)s') 

def worker(): 
     t = threading.currentThread() 
     pause = random.randint(1,10) 
     logging.debug('sleeping %s', pause) 
     time.sleep(pause) 
     logging.debug('ending sleep') 
     return 

threads = [] 

for i in range(3): 
     t = threading.Thread(target=worker,name='t%s'%i) 
     t.setDaemon(True) 
     t.start() 
     threads.append(t) 

for t in threads: 
     logging.debug('joining %s', t.getName()) 
     t.join() 

Ausgang wird

2016-11-22 15:16:51,230 (t0  ) sleeping 10 
2016-11-22 15:16:51,232 (t1  ) sleeping 8 
2016-11-22 15:16:51,233 (t2  ) sleeping 4 
2016-11-22 15:16:51,234 (MainThread) joining t0 
2016-11-22 15:16:55,235 (t2  ) ending sleep 
2016-11-22 15:16:59,241 (t1  ) ending sleep 
2016-11-22 15:17:01,234 (t0  ) ending sleep 
2016-11-22 15:17:01,235 (MainThread) joining t1 
2016-11-22 15:17:01,235 (MainThread) joining t2