Latest web development tutorials

python3 Multithreading

Plusieurs threads exécutés simultanément est similaire à un certain nombre de programmes différents, le fonctionnement multithread présente les avantages suivants:

  • Utilisation de threads peuvent occuper à long programme dans la tâche en arrière-plan pour traiter.
  • L'interface utilisateur peut être plus attrayant, ainsi par exemple que l'utilisateur clique sur un bouton pour déclencher une gestion des événements, vous pouvez pop une barre de progression pour montrer les progrès du processus
  • la vitesse de course pourrait accélérer
  • Sur réalisé certaines tâches, telles que l'attente pour l'entrée utilisateur, le document d'alphabétisation et réseau pour envoyer et recevoir des données, le fil est plus utile. Dans ce cas, nous pouvons libérer des ressources précieuses, telles que l'utilisation de la mémoire et ainsi de suite.

Discussions dans le processus de mise en œuvre et le processus est différent. Chacun a un thread séparé en cours d'exécution d'entrée, la séquence de sortie et les procédures pour la mise en œuvre de l'ordre. Mais le fil ne sont pas en mesure d'effectuer de façon indépendante, il doit exister en fonction de l'application, fournissant de multiples fils d'exécution contrôlées par l'application.

Chaque thread a son propre ensemble de registres CPU, appelé le contexte du fil, le contexte de fil reflète la dernière exécution de l'état du fil de registre de CPU.

pointeur d'instruction et pointeur de la pile des registres sont les deux plus importants registres de contexte de fil, le fil se fait toujours exécuter dans le contexte du processus, ces adresses sont utilisées pour marquer le processus qui possède le fil de l'espace d'adressage de la mémoire.

  • Discussion peut être préempté (interrompu).
  • Dans d'autres fils sont en cours d'exécution, le fil peut être maintenu en suspens (également connu sous le sommeil) - ce qui est le fil de concessions.

Discussion peut être divisé en:

  • Kernel threads: le noyau du système d'exploitation créé et détruit.
  • fils de l' utilisateur: support du noyau et ne nécessite pas le programme utilisateur mis en œuvre fil.

Python3 dénominateur commun de deux modules:

  • _thread
  • threading (recommandé)

module de fil a été abandonné. Les utilisateurs peuvent utiliser le module de filetage à la place. Donc, en python3 ne peut plus utiliser le module "thread". Pour la compatibilité, le fil python3 va renommer "_thread".


Commencer à apprendre fils Python

fils de Python utilisés de deux manières: avec une fonction ou une classe pour envelopper l'objet thread.

Fonctionnel: Appel de la fonction _thread Module start_new_thread () pour générer un nouveau thread. La syntaxe est la suivante:

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

Description Paramètre:

  • - Fonction de fil.
  • args - les paramètres de fil passés à la fonction, il doit être un type de tuple.
  • kwargs - en option.

exemple:

#!/usr/bin/python3

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: 无法启动线程")

while 1:
   pass

Les résultats de sortie du programme ci-dessus sont les suivantes:

Thread-1: Wed Apr  6 11:36:31 2016
Thread-1: Wed Apr  6 11:36:33 2016
Thread-2: Wed Apr  6 11:36:33 2016
Thread-1: Wed Apr  6 11:36:35 2016
Thread-1: Wed Apr  6 11:36:37 2016
Thread-2: Wed Apr  6 11:36:37 2016
Thread-1: Wed Apr  6 11:36:39 2016
Thread-2: Wed Apr  6 11:36:41 2016
Thread-2: Wed Apr  6 11:36:45 2016
Thread-2: Wed Apr  6 11:36:49 2016

Après l'exécution de la procédure ci-dessus peut appuyer sur ctrl-c pour quitter.


Module threading

Python3 fournir un soutien pour enfiler à travers deux _thread de bibliothèque standard et le filetage.

_thread fournit un niveau faible, le fil original et une serrure simple, il est comparé au module de fonction de filetage est encore relativement limitée.

D'autres méthodes, en plus de module de filetage contient le module _thread toutes les méthodes, mais aussi à fournir:

  • threading.currentThread (): Renvoie la variable de thread courant.
  • threading.enumerate (): Renvoie une liste de threads en cours d'exécution contient. Désigne l'exécution du fil a commencé avant la fin, il ne comprend pas le fil avant de commencer et après la résiliation.
  • threading.activeCount (): Retourne le nombre de threads qui sont en cours d'exécution, et len ​​(threading.enumerate ()) ont le même résultat.

En plus de l'utilisation de méthodes, module de filetage fournit également une classe Thread pour manipuler le fil, classe Thread fournit les méthodes suivantes:

  • run (): pour indiquer la méthode de threads actifs.
  • start (): démarrer l' activité de fil.

  • join ([temps]): Attendez jusqu'à ce que le fil est interrompue.Cela bloque le thread appelant jusqu'à rejoindre () la méthode du fil est appelé suspension - sortie normale ou de jeter une exception non gérée - ou timeout option se produit.
  • isAlive (): Retourne le fil est active.
  • getName (): Renvoie le nom de fil.
  • setName (): Définissez le nom de fil.

Utilisez le module threading pour créer un fil

Nous pouvons être créés directement héritée de threading.Thread une nouvelle sous-classe, après la méthode start et instancier (appel) pour démarrer un nouveau thread, qu'il appelle la méthode d'exécution du thread ():

#!/usr/bin/python3

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 ("开始线程:" + self.name)
        print_time(self.name, self.counter, 5)
        print ("退出线程:" + self.name)

def print_time(threadName, delay, counter):
    while counter:
        if exitFlag:
            threadName.exit()
        time.sleep(delay)
        print ("%s: %s" % (threadName, time.ctime(time.time())))
        counter -= 1

# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# 开启新线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("退出主线程")

Les résultats de l'exécution du programme ci-dessus sont les suivantes;

开始线程:Thread-1
开始线程:Thread-2
Thread-1: Wed Apr  6 11:46:46 2016
Thread-1: Wed Apr  6 11:46:47 2016
Thread-2: Wed Apr  6 11:46:47 2016
Thread-1: Wed Apr  6 11:46:48 2016
Thread-1: Wed Apr  6 11:46:49 2016
Thread-2: Wed Apr  6 11:46:49 2016
Thread-1: Wed Apr  6 11:46:50 2016
退出线程:Thread-1
Thread-2: Wed Apr  6 11:46:51 2016
Thread-2: Wed Apr  6 11:46:53 2016
Thread-2: Wed Apr  6 11:46:55 2016
退出线程:Thread-2
退出主线程

Synchronisation Thread

Si plusieurs threads d'une modification de données commune, des résultats imprévisibles peuvent se produire, afin d'assurer l'exactitude des données, nous avons besoin de synchroniser plusieurs threads.

objet Thread utilisant le verrou et RLOCK peut réaliser une synchronisation de fil simple, les deux objets ont des méthodes d'acquérir et de méthodes de libération, pour ceux qui ont besoin chacun permettant seulement une donnée de fonctionnement de fil, il peut être mis en service à acquérir et à libérer les méthodes de la la chambre. Comme suit:

Multithreading avantage est qu'il peut exécuter simultanément des tâches multiples (au moins se sent comme ça). Mais lorsque les discussions ont besoin de partager des données, il peut y avoir aucun problème de synchronisation des données.

Prenons un cas: une liste de tous les éléments sont nuls, le fil "set" de l'arrière vers l'avant tous les éléments en un seul, et le fil "print" d'avant en arrière en charge de la lecture de la liste et l'impression.

Ensuite, le fil peut être "réglé" a commencé à changer lorsque le fil "print" pour imprimer une liste, il serait la moitié de la sortie d'un demi-0, ce qui est les données ne sont pas synchronisées. Pour éviter cette situation, nous introduisons le concept de la serrure.

Verrouiller a deux états - verrouillé et déverrouillé. Chaque fois un fil tel que le "set" pour accéder aux données partagées, vous devez d'abord obtenir le verrou, si vous avez déjà un autre thread, comme "print" pour obtenir enfermé, puis laisser le fil "set" pause, ce qui est le blocage synchrone; attendre jusqu'à ce que le fil " imprimer "l'accès est terminé, après la sortie de la serrure, laissez le fil" set "pour continuer.

Après ce processus, lorsque vous imprimez une liste de toutes les sorties 0 ou 1 sortie complète, ne semble plus la moitié embarras 0 1 demi.

exemple:

#!/usr/bin/python3

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 ("开启线程: " + 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 ("退出主线程")

Le programme ci-dessus, le résultat est:

开启线程: Thread-1
开启线程: Thread-2
Thread-1: Wed Apr  6 11:52:57 2016
Thread-1: Wed Apr  6 11:52:58 2016
Thread-1: Wed Apr  6 11:52:59 2016
Thread-2: Wed Apr  6 11:53:01 2016
Thread-2: Wed Apr  6 11:53:03 2016
Thread-2: Wed Apr  6 11:53:05 2016
退出主线程

file d'attente prioritaire Thread (file d'attente)

Le module Queue de Python fournit la synchronisation, les classes de file d'attente thread-safe, y compris FIFO (first in first out) file d'attente de file d'attente, LIFO (dernier entré, premier sorti) file d'attente LifoQueue et file d'attente prioritaire PriorityQueue.

Ces files d'attente sont mises en œuvre primitives de verrouillage peuvent être utilisés directement dans un multithread, vous pouvez utiliser la file d'attente pour obtenir une synchronisation entre les threads.

module Queue méthodes couramment utilisées:

  • Queue.qsize () retourne la taille de la file d'attente
  • Queue.empty () si la file d'attente est vide, renvoie True, False et vice versa
  • Queue.full () Si la file d'attente est pleine, le retour True, False et vice versa
  • Correspondant à la taille et maxsize Queue.full
  • Queue.get ([bloc [timeout]]) Obtient la file d'attente, délai d'attente le temps d'attente
  • Queue.get_nowait () plutôt Queue.get (Faux)
  • Queue.put (point) de file d'attente d'écriture, délai d'attente le temps d'attente
  • Queue.put_nowait (point) tout à fait Queue.put (point, False)
  • Queue.task_done () après l'achèvement d'une œuvre, Queue.task_done () fonction envoie un signal à la tâche a été achevée file d'attente
  • Queue.join () signifie vraiment jusqu'à ce que la file d'attente est vide, puis effectuer d'autres opérations

exemple:

#!/usr/bin/python3

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 ("开启线程:" + self.name)
        process_data(self.name, self.q)
        print ("退出线程:" + 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 ("退出主线程")

Les résultats du programme ci-dessus:

开启线程:Thread-1
开启线程:Thread-2
开启线程:Thread-3
Thread-3 processing One
Thread-1 processing Two
Thread-2 processing Three
Thread-3 processing Four
Thread-1 processing Five
退出线程:Thread-3
退出线程:Thread-2
退出线程:Thread-1
退出主线程