Multithreading en python (résumé)

WBOY
Libérer: 2022-11-16 16:56:32
avant
14306 Les gens l'ont consulté

Cet article vous apporte des connaissances pertinentes sur Python, qui présente principalement le contenu pertinent sur le multi-threading. Plusieurs threads peuvent s'exécuter dans le même programme, et chaque thread effectue des tâches différentes. Jetons un coup d'œil, j'espère que cela vous aidera. tout le monde.

Multithreading en python (résumé)

【Recommandation connexe : Tutoriel vidéo Python3

python multi-threading

1. Le concept de thread

Le thread est l'unité de base permettant au CPU d'allouer des ressources. Lorsqu'un programme démarre, il devient un processus et un processus équivaut à un ou plusieurs threads. Lorsqu'il n'y a pas de programmation multi-thread, un processus est équivalent à un thread principal ; lorsqu'il y a une programmation multi-thread, un processus contient plusieurs threads (y compris le thread principal). Le développement de programmes de grande envergure peut être réalisé à l’aide de threads.

Plusieurs threads peuvent s'exécuter dans le même programme et chaque thread effectue des tâches différentes.

Le programme de service en arrière-plan multithread peut gérer plusieurs tâches en même temps sans blocage.

La caractéristique de la programmation multithread est qu'elle peut améliorer l'efficacité d'exécution du programme et la vitesse de traitement. Les programmes Python peuvent exécuter plusieurs threads relativement indépendants en parallèle en même temps.

2. Créer des multi-threads

Python prend en charge deux façons de créer des multi-threads :

~Créé via threading.Thread ().

~En héritant de la classe threading.Thread.

1. Créez

via threading.Thread () Forme grammaticale :

thread.Thread(group=Nore,targt=None,args=(),kwargs={},*,daemon=None)
Copier après la connexion

Explication du paramètre :

~group : doit être None, lié à la classe ThreadGroup, généralement non utilisé.

~target : L'objet appelé par le thread est la fonction cible.

~nom : Donnez ce nom au fil de discussion. La valeur par défaut est Tread-x, x est le numéro de série, commençant à 1, et le nom du premier thread créé est Tread-1.

~args : passez les arguments des mots-clés, le dictionnaire pour la fonction cible.

~démon : utilisé pour définir si le thread se termine lorsque le thread principal se termine.

Exemple :

import threading
def test (x,y):
 for i in range(x,y):
   print(i)
thread1 = threading.Thread(name='t1',target= test,args=(1,10))
thread2 = threading.Thread(name='t2',target= test,args=(11,20))
thread1.start()   #启动线程1
thread2.start()   #启动线程2
Copier après la connexion

Sortie :

1
2
3
4
5
6
7
8
9
11
12
13
14
15
16
17
18
19
Copier après la connexion

Explication : Les deux programmes s'exécuteront simultanément, donc les résultats ne sont pas nécessairement séquentiels de 1 à 10 à chaque fois. Ceci est basé sur le segment de temps alloué par le CPU aux deux threads. Décider. Vous pouvez voir que les résultats sont différents à chaque fois.

2. Héritage par héritage de la classe threading.Thread

threading.Thread est une classe et peut être héritée.

Exemple :

import threading
class mythread(threading.Thread):
  def run(self):
    for i in range(1,10):
      print(i)
thread1 = mythread();
thread2 = mythread();
thread1.start()
thread2.start()
Copier après la connexion

Sortie :

1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
Copier après la connexion

Explication : Personnalisez une classe pour hériter de threading.Thread, puis remplacez la méthode run de la classe parent. Cette méthode sera automatiquement exécutée au démarrage du thread (exécuter start()). .

3. Thread principal

En python, le thread principal est le premier thread à démarrer.

~Thème parent : Si un thread B est démarré dans le thread de départ A, A est le thread parent de B.

~Sous-thread : B est le sous-thread de A.

Il existe un attribut damon lors de la création d'un fil de discussion, utilisez-le pour déterminer le fil de discussion principal. Lorsque le démon est défini sur False, le thread ne se terminera pas lorsque le thread principal se terminera et le thread principal attendra que le thread enfant termine son exécution. Lorsque le démon est défini sur True, le thread se fermera à la fin du thread principal et les autres threads enfants seront forcés de se fermer à la fin du thread principal.

Remarque lors de l'utilisation du démon :

~L'attribut du démon doit être défini avant start(), sinon une exception RuntimeError sera levée

~Chaque thread a un attribut du démon, qui peut être défini ou non. S'il n'est pas défini, la valeur par défaut est Aucun.

~Si le thread enfant ne définit pas l'attribut du démon, prenez le démon du thread actuel pour le définir. Le thread enfant hérite de la valeur du démon du thread enfant, ce qui a le même effet que la définition de None.

~Si l'attribut démon n'est pas défini pour tous les threads créés à partir du thread principal, la valeur par défaut est daemon=False.

Exemple :

import time
import threading
def test():
 time.sleep(10)
 for i in range(10):
  print(i)
thread1 = threading.Thread(target=test,daemon=False)
thread1.start()
print('主线程完成了')
Copier après la connexion

Sortie :

主线程完成了
0
1
2
3
4
5
6
7
8
9
Copier après la connexion

Explication : Lorsque le thread principal termine son exécution et génère une sortie, attendez un moment, puis affichez 0~9. Si daemon=False est remplacé par daemon=True, l'instruction for i in range(10) ne sera pas exécutée.

4. Blocage des threads

Lorsqu'un thread appelle la méthode de jointure d'un autre thread, l'appelant est bloqué jusqu'à ce que le thread appelant soit terminé.

Forme grammaticale :

join(timeout-=None)
Copier après la connexion

Le paramètre timeout spécifie la durée d'attente de l'appelant. S'il n'est pas défini, il attendra la fin du thread appelé et la fin du thread appelé. Parmi eux, un fil de discussion peut être appelé plusieurs fois par jointure.

Exemple :

import time
import threading
def test():
 time.sleep(5)
 for i in range(10):
  print(i)
thread1=threading.Thread(target=test)
thread1.start()
thread1.join()
print('主线程完成了')
Copier après la connexion

Sortie :

0
1
2
3
4
5
6
7
8
9
主线程完成了
Copier après la connexion

Explication : Ajoutez thread1.join() après thread1.start() pour ajouter la méthode de jointure Lors de la sortie, le thread principal attendra que 0~9 soit affiché avant de l'exécuter. propre sortie d’impression.

5. Déterminez si le fil de discussion est actif

~run() : une méthode utilisée pour indiquer l'activité du fil de discussion

~start() : démarre le fil de discussion

~join() : attend que le fil de discussion se termine

~isAlive() : renvoie si le fil de discussion est actif

~getName() : renvoie le nom du fil de discussion

~setName() : définit le nom du fil de discussion

Exemple :

from threading import Thread, Event
import time
def countdown(n, started_evt):
    print('正在运行')
    started_evt.set()
    while n > 0:
        print('时间', n)
        n -= 1
        time.sleep(2)
started_evt = Event()
print('开始倒计时')
t = Thread(target=countdown, args=(10, started_evt))
t.start()
started_evt.wait()
print('倒计时运行')
Copier après la connexion

Sortie :

开始倒计时
正在运行
时间 10
倒计时运行
时间 9
时间 8
时间 7
时间 6
时间 5
时间 4
时间 3
时间 2
时间 1
Copier après la connexion

Alive,顾名思义,它表示线程当前是否为可用状态,如果线程已经启动,并且当前没有任何异常的话,则返回true,否则为false

Thread.isAlive() :顾名思义,是表示当前线程时候为可用状态,即是否已经在启动,并且在运行的状态;

六、线程同步

1.同步概念

异步模式的情况下,同时有一个线程在修改共享数据,另一个线程在读取共享数据,当修改的共享数据的线程没有处理完毕,读取数据的线程肯定会得到错误的结果。如果采用多线程的同步控制机制,当处理共享数据的线程完成处理数据之后,读取线程就读取数据。

python的锁就解决这一问题,锁住线程,只允许一个线程操作,其他线程排队等待,待当前线程操作完毕后,再按顺序一个一个来运行。

2. python的锁

python的threading模块提供了RLock锁解决方法。在某一时间只能让一个线程操作的语句放到RLock的acquire方法和release方法之间,即acquire相当于给RLack上锁,而release相当于解锁。

示例:

import threading
class mythread(threading.Thread):
 def run(self):
  global x                   #声明一个全局变量
  lock.acquire()             #上锁
  x +=10
  print('%s:%d'%(self.name,x))
  lock.release()             #解锁
x = 0                        #设置全局变量初始值
lock = threading.RLock()     #创建可重入锁
list1 = []                   
for i in range(5):   
 list1.append(mythread())    #创建五个线程,放到同一列表中
for i in list1:
 i.start()                   #开启列表线程
Copier après la connexion

输出:

Thread-1:10
Thread-2:20
Thread-3:30
Thread-4:40
Thread-5:50
Copier après la connexion

解释:

3. python中的条件锁

条件锁常用的方法:

~acquire([timeout]):调用关联锁的方法

~release():解锁

~wait():使线程进入 Condition 的等待池等待通知并释放解锁。使用前线程必须已获得锁定,否则将抛出异常。

~notify():从等待池挑选一个线程并通知,收到通知的线程将自动调用 acquire() 尝试获得,其他线程仍然在等待池中等待通知,直到该线程收到通知 调用该方法,否则将会抛出异常。

~notify ALL():跟notify() 一样,但这个方法对应的是所有的线程。

示例:

题目:有几个生产车间生产,几个消费者购买,当生产达到一定数量时,停止生产。

import threading
import time
condtion = threading.Condition()
sheep = ['1件产品','1件产品','1件产品','1件产品','1件产品']
class Producer(threading.Thread):
    def __init__(self, name):
        super().__init__(name=name)
        pass
    def run(self):
        global condtion, sheep
        while True:
            time.sleep(0.1)
            condtion.acquire()
            if len(sheep) < 10:
                print(self.name + "生产了1件产品")
                sheep.append(&#39;1件产品&#39;)
                condtion.notifyAll()
                pass
            else:
                print("仓库满了,停止生产!")
                condtion.wait()
                pass
            condtion.release()
        pass
    pass
class Customer(threading.Thread):
    def __init__(self, name):
        super().__init__(name=name)
        pass
    def run(self):
        global condtion, sheep
        while True:
            time.sleep(0.1)
            condtion.acquire()
            if len(sheep) > 0:
                meat = sheep.pop()
                print(self.name + "购买了" + meat + "还剩多少" + str(len(sheep)) + "件")
                condtion.notifyAll()
                pass
            else:
                print("买光了,等待")
                condtion.wait()
                pass
            condtion.release()
        pass
    pass
if __name__ == "__main__":
    p1 = Producer("1号生产车间")
    p2 = Producer("2号生产车间")
    p3 = Producer("3号生产车间")
    p4 = Producer("4号生产车间")
    p5 = Producer("5号生产车间")
    p6 = Producer("6号生产车间")
    p1.start()
    p2.start()
    p4.start()
    p5.start()
    p6.start()
    c1 = Customer('小王')
    c2 = Customer('小李')
    c3 = Customer('小贾')
    c4 = Customer('小沈')
    c5 = Customer('小刘')
    c1.start()
    c2.start()
    c3.start()
    c4.start()
    c5.start()
Copier après la connexion

【相关推荐:Python3视频教程

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!

Étiquettes associées:
source:csdn.net
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal