Maison  >  Article  >  développement back-end  >  Vous amène à interpréter le multithreading Python

Vous amène à interpréter le multithreading Python

WBOY
WBOYavant
2022-03-02 17:35:482401parcourir

Cet article vous apporte des connaissances pertinentes sur python, qui présente principalement les connaissances pertinentes sur le multi-threading est similaire à l'exécution de plusieurs programmes différents en même temps. Il présente de nombreux avantages. . J'espère que cela aidera tout le monde.

Vous amène à interpréter le multithreading Python

Apprentissage recommandé : Tutoriel Python

Explication du thread

 Le multi-threading est similaire à l'exécution de plusieurs programmes différents en même temps. Le multi-threading présente les avantages suivants :

  • L'utilisation de threads peut réduire le nombre. de programmes qui occupent beaucoup de temps La tâche est placée en arrière-plan pour le traitement.
  • L'interface utilisateur peut être plus attrayante, de sorte que si l'utilisateur clique sur un bouton pour déclencher le traitement de certains événements, une barre de progression peut apparaître pour afficher la progression du traitement.
  • Le programme peut s'exécuter plus rapidement.
  • Les threads sont plus utiles dans la mise en œuvre de certaines tâches en attente telles que la saisie utilisateur, la lecture et l'écriture de fichiers, ainsi que l'envoi et la réception de données sur le réseau. Dans ce cas, nous pouvons libérer certaines ressources précieuses telles que l'utilisation de la mémoire, etc.

  Il y a une différence entre un thread et un processus lors de l'exécution. Chaque thread indépendant possède un point d'entrée pour l'exécution du programme, une séquence d'exécution séquentielle et un point de sortie pour le programme. Cependant, les threads ne peuvent pas s'exécuter indépendamment et doivent exister dans le programme d'application, et le programme d'application fournit un contrôle d'exécution de plusieurs threads.
 Chaque thread possède son propre ensemble de registres CPU, appelé contexte du thread, qui reflète l'état des registres CPU du thread exécuté en dernier lieu.
Le pointeur d'instruction et le registre de pointeur de pile sont les deux registres les plus importants dans le contexte du thread. Le thread s'exécute toujours dans le contexte du processus. Ces adresses sont utilisées pour marquer la mémoire dans l'espace d'adressage du processus. à qui appartient le fil.
 Les fils de discussion peuvent être préemptés (interrompus).
Les threads peuvent être mis en attente (également appelés en veille) pendant que d'autres threads sont en cours d'exécution – c'est ce qu'on appelle l'arrêt des threads.
Les threads peuvent être divisés en :

  • Threads du noyau : créés et révoqués par le noyau du système d'exploitation.
  • Thread utilisateur : un thread implémenté dans le programme utilisateur sans support du noyau.

 Deux modules couramment utilisés dans les threads Python3 sont :

  • _thread
  • threading (recommandé)

 le module thread a été abandonné. Les utilisateurs peuvent utiliser le module de thread à la place. Le module "thread" ne peut donc plus être utilisé en Python3. Pour des raisons de compatibilité, Python3 a renommé le thread en "_thread".

Commencez à apprendre les threads Python

  Il existe deux façons d'utiliser les threads en Python : des fonctions ou des classes pour envelopper des objets thread.
Fonctionnel : Appelez la fonction start_new_thread() dans le module _thread pour générer un nouveau thread. La syntaxe est la suivante :

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

  Description du paramètre :

  • function - fonction thread.
  • args - les paramètres passés à la fonction thread, il doit être de type tuple.
  • kwargs - paramètres facultatifs.

  Exemple :

#!/usr/bin/python3

import _thread
import time

# 为线程定义一个函数
def print_time( threadName, delay):
    count = 0
    while count <p>  Le résultat de l'exécution du programme ci-dessus est le suivant : <br><img src="https://img.php.cn/upload/article/000/000/067/9e54370fdafb34f8739135c680e1aa53-0.png" alt="Vous amène à interpréter le multithreading Python"></p><h2>Module Threading</h2><p>  Python3 fournit la prise en charge des threads via deux bibliothèques standard _thread et threading. </p>
  • _thread fournit des threads primitifs de bas niveau et un simple verrou. Ses fonctions sont relativement limitées par rapport au module de threading. En plus de toutes les méthodes du module _thread, le module
  • threading fournit également d'autres méthodes :
  • threading.currentThread() : renvoie la variable de thread actuelle.
  • threading.enumerate() :
    Renvoie une liste contenant les threads en cours d'exécution. L'exécution fait référence au thread après son démarrage et avant sa fin, à l'exclusion des threads avant le démarrage et après la fin.
  • threading.activeCount() :
    Renvoie le nombre de threads en cours d'exécution, qui a le même résultat que len(threading.enumerate()).

  En plus des méthodes d'utilisation, le module thread fournit également la classe Thread pour gérer les threads. La classe Thread fournit les méthodes suivantes :

  • run() : Une méthode utilisée pour représenter l'activité des threads.
  • start() : démarre l'activité du fil de discussion.
  • join([time]) : attendez que le fil de discussion se termine. Cela bloque le thread appelant jusqu'à ce que la méthode join()
    du thread soit abandonnée - en se terminant normalement ou en lançant une exception non gérée - ou jusqu'à ce qu'un délai d'attente facultatif se produise.
  • isAlive() : indique si le fil de discussion est actif.
  • getName() : renvoie le nom du fil de discussion.
  • setName() : définit le nom du fil de discussion.

Utilisez le module threading pour créer des threads

Nous pouvons créer une nouvelle sous-classe en héritant directement de threading.Thread, et appeler la méthode start() pour démarrer un nouveau thread après l'instanciation, c'est-à-dire qu'elle appelle l'exécution du thread( ) méthode :

#!/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 d'exécution du programme ci-dessus sont les suivants :
Vous amène à interpréter le multithreading Python

线程同步

  如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。
  使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。如下:
  多线程的优势在于可以同时运行多个任务(至少感觉起来是这样)。但是当线程需要共享数据时,可能存在数据不同步的问题。
  考虑这样一种情况:一个列表里所有元素都是0,线程"set"从后向前把所有元素改成1,而线程"print"负责从前往后读取列表并打印。
  那么,可能线程"set"开始改的时候,线程"print"便来打印列表了,输出就成了一半0一半1,这就是数据的不同步。为了避免这种情况,引入了锁的概念。
  锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print"获得锁定了,那么就让线程"set"暂停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续。
  经过这样的处理,打印列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。
  实例:

#!/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 ("退出主线程")

  执行以上程序,输出结果为:
Vous amène à interpréter le multithreading Python

线程优先级队列(Queue)

  Python 的 Queue 模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列 PriorityQueue。
  这些队列都实现了锁原语,能够在多线程中直接使用,可以使用队列来实现线程间的同步。
  Queue 模块中的常用方法:

  • Queue.qsize() 返回队列的大小
  • Queue.empty() 如果队列为空,返回True,反之False
  • Queue.full() 如果队列满了,返回True,反之False
  • Queue.full 与 maxsize 大小对应
  • Queue.get([block[, timeout]])获取队列,timeout等待时间
  • Queue.get_nowait() 相当Queue.get(False)
  • Queue.put(item) 写入队列,timeout等待时间
  • Queue.put_nowait(item) 相当Queue.put(item, False)
  • Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
  • Queue.join() 实际上意味着等到队列为空,再执行别的操作

  实例:

#!/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 ("退出主线程")

  以上程序执行结果:
Vous amène à interpréter le multithreading Python

 推荐学习:python学习教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer