Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> Python

Maîtriser la programmation multithread en Python : Techniques de concurrence efficaces

Exécuter plusieurs threads revient à exécuter plusieurs programmes simultanément, mais avec les avantages suivants :

Un thread a un début, une séquence d'exécution et une conclusion. Il a un pointeur d'instruction qui suit où il s'exécute dans son contexte.

Démarrage d'un nouveau thread

Pour engendrer un autre thread, appelez la méthode suivante du module thread :

thread.start_new_thread(function, args[, kwargs])

Cet appel permet une création rapide et efficace de threads sous Linux et Windows.

L'appel retourne immédiatement et le thread enfant démarre et appelle function avec la liste args. Quand la fonction retourne, le thread se termine.

args est un tuple d'arguments ; utilisez un tuple vide pour appeler sans arguments. kwargs est un dictionnaire optionnel d'arguments nommés.

Exemple

#!/usr/bin/python
import thread
import time

def print_time(threadName, delay):
    count = 0
    while count < 5:
        time.sleep(delay)
        count += 1
        print("%s: %s" % (threadName, time.ctime(time.time())))

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

Résultat :

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'efficace pour le threading de bas niveau, le module thread est très limité comparé au module threading plus récent.

Le module Threading

Le module threading inclus avec Python 2.4 fournit un support bien plus puissant et de haut niveau pour les threads que le module thread.

Le module threading expose toutes les méthodes du module thread et fournit des méthodes supplémentaires :

En plus, le module threading a la classe Thread qui implémente le threading. Méthodes de la classe Thread :

Création d'un thread avec le module Threading

Pour implémenter un nouveau thread avec threading :

Une fois la sous-classe créée, instanciez-la et démarrez un nouveau thread avec start(), qui appelle run().

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

# Créer nouveaux threads
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# Démarrer nouveaux threads
thread1.start()
thread2.start()

print("Exiting Main Thread")

Résultat :

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

Synchronisation des threads

Le module threading inclut un mécanisme de verrouillage simple pour synchroniser les threads. Un nouveau verrou est créé par Lock().

La méthode acquire(blocking) force les threads à s'exécuter de façon synchrone. Le paramètre optionnel blocking contrôle si le thread attend pour acquérir le verrou.

La méthode release() libère le verrou quand 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)
        threadLock.acquire()
        print_time(self.name, self.counter, 3)
        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 = []

thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

thread1.start()
thread2.start()

threads.append(thread1)
threads.append(thread2)

for t in threads:
    t.join()

print("Exiting Main Thread")

Résultat :

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 de priorité multithread

Le module Queue permet de créer un objet file pouvant contenir un nombre spécifique d'éléments. Méthodes de contrôle :

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

for tName in threadList:
    thread = myThread(threadID, tName, workQueue)
    thread.start()
    threads.append(thread)
    threadID += 1

queueLock.acquire()
for word in nameList:
    workQueue.put(word)
queueLock.release()

while not workQueue.empty():
    pass

exitFlag = 1

for t in threads:
    t.join()

print("Exiting Main Thread")

Résultat :

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

  1. Maîtriser les types de données Python : Guide pratique
  2. Maîtriser les opérateurs Python : Guide complet
  3. Maîtriser l'instruction pass en Python : Guide pratique
  4. Maîtriser les arguments de fonctions Python : Positionnels, nommés et paramètres par défaut
  5. Maîtriser les dictionnaires Python : création, manipulation et techniques avancées
  6. Maîtriser la programmation orientée objet Python : classes, héritage, encapsulation et polymorphisme
  7. Programmation réseau en Python : Maîtriser les sockets et protocoles avancés
  8. Maîtriser la programmation d'extensions Python avec C : Construire des modules natifs rapides
  9. Maîtriser le Cycle de Filetage Fanuc G76 : Guide Complet pour Opérateurs CNC