Python - Programmation multithread
Page PrécédentePage Suivante
L'exécution de plusieurs threads est similaire à l'exécution simultanée de plusieurs programmes différents, mais avec les avantages suivants −
-
Plusieurs threads au sein d'un processus partagent le même espace de données avec le thread principal et peuvent donc partager des informations ou communiquer entre eux plus facilement que s'il s'agissait de processus séparés.
-
Les threads sont parfois appelés processus légers et ne nécessitent pas beaucoup de surcharge de mémoire. ils sont moins chers que les processus.
Un thread a un début, une séquence d'exécution et une conclusion. Il a un pointeur d'instruction qui garde une trace de l'endroit où il est en cours d'exécution dans son contexte.
-
Il peut être préempté (interrompu)
-
Il peut être temporairement mis en attente (également appelé sommeil) pendant que d'autres threads sont en cours d'exécution - c'est ce qu'on appelle céder.
Démarrer un nouveau fil
Pour générer un autre thread, vous devez appeler la méthode suivante disponible dans thread modules −
thread.start_new_thread ( function, args[, kwargs] )
Cet appel de méthode permet de créer rapidement et efficacement de nouveaux threads sous Linux et Windows.
L'appel de méthode revient immédiatement et le thread enfant démarre et appelle la fonction avec la liste passée d'args . Lorsque la fonction revient, le thread se termine.
Ici, arguments est un tuple d'arguments ; utilisez un tuple vide pour appeler la fonction sans passer d'arguments. kwargs est un dictionnaire facultatif d'arguments de mots clés.
Exemple
#!/usr/bin/python import thread import time # Define a function for the thread def print_time( threadName, delay): count = 0 while count < 5: time.sleep(delay) count += 1 print "%s: %s" % ( threadName, time.ctime(time.time()) ) # Create two threads as follows try: thread.start_new_thread( print_time, ("Thread-1", 2, ) ) thread.start_new_thread( print_time, ("Thread-2", 4, ) ) except: print "Error: unable to start thread" while 1: pass
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant −
Thread-1: Thu Jan 22 15:42:17 2009 Thread-1: Thu Jan 22 15:42:19 2009 Thread-2: Thu Jan 22 15:42:19 2009 Thread-1: Thu Jan 22 15:42:21 2009 Thread-2: Thu Jan 22 15:42:23 2009 Thread-1: Thu Jan 22 15:42:23 2009 Thread-1: Thu Jan 22 15:42:25 2009 Thread-2: Thu Jan 22 15:42:27 2009 Thread-2: Thu Jan 22 15:42:31 2009 Thread-2: Thu Jan 22 15:42:35 2009
Bien qu'il soit très efficace pour le threading de bas niveau, mais le thread est très limité par rapport au nouveau module de threading.
Le threading Module
Le nouveau module de threading inclus avec Python 2.4 fournit une prise en charge de haut niveau beaucoup plus puissante pour les threads que le module de thread discuté dans la section précédente.
Le threading module expose toutes les méthodes du thread module et fournit quelques méthodes supplémentaires −
-
threading.activeCount() − Renvoie le nombre d'objets thread qui sont actifs.
-
threading.currentThread() − Renvoie le nombre d'objets thread dans le contrôle de thread de l'appelant.
-
threading.enumerate() − Renvoie une liste de tous les objets threads actuellement actifs.
En plus des méthodes, le module de threading a le Thread classe qui implémente le threading. Les méthodes fournies par le Thread classe sont les suivantes −
-
exécuter() − La méthode run() est le point d'entrée d'un thread.
-
démarrer() − La méthode start() démarre un thread en appelant la méthode run.
-
rejoindre([heure]) − Le join() attend que les threads se terminent.
-
est vivant() − La méthode isAlive() vérifie si un thread est toujours en cours d'exécution.
-
getName() − La méthode getName() retourne le nom d'un thread.
-
setName() − La méthode setName() définit le nom d'un thread.
Créer un fil à l'aide de Threading Module
Pour implémenter un nouveau thread à l'aide du module de threading, vous devez faire ce qui suit −
-
Définir une nouvelle sous-classe du Thread classe.
-
Remplacer le __init__(self [,args]) méthode pour ajouter des arguments supplémentaires.
-
Ensuite, remplacez la méthode run(self [,args]) pour implémenter ce que le thread doit faire au démarrage.
Une fois que vous avez créé le nouveau Thread sous-classe, vous pouvez en créer une instance, puis démarrer un nouveau thread en appelant start() , qui à son tour appelle run() méthode.
Exemple
#!/usr/bin/python import threading import time exitFlag = 0 class myThread (threading.Thread): def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print "Starting " + self.name print_time(self.name, 5, self.counter) print "Exiting " + self.name def print_time(threadName, counter, delay): while counter: if exitFlag: threadName.exit() time.sleep(delay) print "%s: %s" % (threadName, time.ctime(time.time())) counter -= 1 # Create new threads thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() print "Exiting Main Thread"
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant −
Starting Thread-1 Starting Thread-2 Exiting Main Thread Thread-1: Thu Mar 21 09:10:03 2013 Thread-1: Thu Mar 21 09:10:04 2013 Thread-2: Thu Mar 21 09:10:04 2013 Thread-1: Thu Mar 21 09:10:05 2013 Thread-1: Thu Mar 21 09:10:06 2013 Thread-2: Thu Mar 21 09:10:06 2013 Thread-1: Thu Mar 21 09:10:07 2013 Exiting Thread-1 Thread-2: Thu Mar 21 09:10:08 2013 Thread-2: Thu Mar 21 09:10:10 2013 Thread-2: Thu Mar 21 09:10:12 2013 Exiting Thread-2
Synchroniser les fils
Le module de threading fourni avec Python comprend un mécanisme de verrouillage simple à mettre en œuvre qui vous permet de synchroniser les threads. Un nouveau verrou est créé en appelant le Lock() qui renvoie le nouveau verrou.
L'acquisition (blocage) La méthode du nouvel objet de verrouillage est utilisée pour forcer les threads à s'exécuter de manière synchrone. Le blocage facultatif Le paramètre vous permet de contrôler si le thread attend pour acquérir le verrou.
Si bloquant est mis à 0, le thread retourne immédiatement avec une valeur 0 si le verrou ne peut pas être acquis et avec un 1 si le verrou a été acquis. Si le blocage est défini sur 1, le thread se bloque et attend que le verrou soit libéré.
Le release() La méthode du nouvel objet de verrouillage est utilisée pour libérer le verrou lorsqu'il n'est plus nécessaire.
Exemple
#!/usr/bin/python import threading import time class myThread (threading.Thread): def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print "Starting " + self.name # Get lock to synchronize threads threadLock.acquire() print_time(self.name, self.counter, 3) # Free lock to release next thread threadLock.release() def print_time(threadName, delay, counter): while counter: time.sleep(delay) print "%s: %s" % (threadName, time.ctime(time.time())) counter -= 1 threadLock = threading.Lock() threads = [] # Create new threads thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() # Add threads to thread list threads.append(thread1) threads.append(thread2) # Wait for all threads to complete for t in threads: t.join() print "Exiting Main Thread"
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant −
Starting Thread-1 Starting Thread-2 Thread-1: Thu Mar 21 09:11:28 2013 Thread-1: Thu Mar 21 09:11:29 2013 Thread-1: Thu Mar 21 09:11:30 2013 Thread-2: Thu Mar 21 09:11:32 2013 Thread-2: Thu Mar 21 09:11:34 2013 Thread-2: Thu Mar 21 09:11:36 2013 Exiting Main Thread
File d'attente prioritaire multithread
La file d'attente Le module vous permet de créer un nouvel objet de file d'attente pouvant contenir un nombre spécifique d'éléments. Il existe les méthodes suivantes pour contrôler la file d'attente −
-
obtenir() − Le get() supprime et renvoie un élément de la file d'attente.
-
mettre() − Le put ajoute un élément à une file d'attente.
-
qsize() − Le qsize() renvoie le nombre d'éléments qui sont actuellement dans la file d'attente.
-
vide() − Le empty( ) renvoie True si la file d'attente est vide; sinon, Faux.
-
plein() − the full() retourne True si la file est pleine; sinon, Faux.
Exemple
#!/usr/bin/python import Queue import threading import time exitFlag = 0 class myThread (threading.Thread): def __init__(self, threadID, name, q): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.q = q def run(self): print "Starting " + self.name process_data(self.name, self.q) print "Exiting " + self.name def process_data(threadName, q): while not exitFlag: queueLock.acquire() if not workQueue.empty(): data = q.get() queueLock.release() print "%s processing %s" % (threadName, data) else: queueLock.release() time.sleep(1) threadList = ["Thread-1", "Thread-2", "Thread-3"] nameList = ["One", "Two", "Three", "Four", "Five"] queueLock = threading.Lock() workQueue = Queue.Queue(10) threads = [] threadID = 1 # Create new threads for tName in threadList: thread = myThread(threadID, tName, workQueue) thread.start() threads.append(thread) threadID += 1 # Fill the queue queueLock.acquire() for word in nameList: workQueue.put(word) queueLock.release() # Wait for queue to empty while not workQueue.empty(): pass # Notify threads it's time to exit exitFlag = 1 # Wait for all threads to complete for t in threads: t.join() print "Exiting Main Thread"
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant −
Starting Thread-1 Starting Thread-2 Starting Thread-3 Thread-1 processing One Thread-2 processing Two Thread-3 processing Three Thread-1 processing Four Thread-2 processing Five Exiting Thread-3 Exiting Thread-1 Exiting Thread-2 Exiting Main Thread
Python