百万年俸のpythonの道 - スレッド限り並行プログラミング

マルチスレッド

1.プロセス:生産者 - 消費者モデル

プログラミングのアイデア、モデル、デザインパターン、理論などが、あなたのプログラミング方法を渡され、以降似たような状況に遭遇し、あなたは適用することができます

生産者と消費者のモデルの3つの要素:
  1. メーカー:データを生成します
  2. 消費者:さらなる処理のために受信データ
  3. コンテナ:バッファ(キュー)はデカップリング、消費者と生産性のバランスをとるためのクッションとして作用します

2.理論的知識スレッド

  1. スレッドとは何ですか

    組立ラインのワークフロー

    プロセス:メモリ内のオープンスペースのプロセス、およびプライマリプロセスのすべてのリソースをコピーし、コードを実行するCPUを呼び出します。

    プロセスは、リソーススケジューリングの基本単位であり、スレッドがCPUの実行の最小単位であります

    IMG

    オープンプロセス:プロセスは、メモリプロセスのスペースをオープンし、メインスレッドにデータをコピーするプロセス全体は、内部コードを実行します

  2. プロセス対スレッド

    1. オープンプロセスのオーバーヘッドは、スレッドのオーバーヘッドよりもはるかに大きく、非常に大きいです。
    2. オープンスレッドの速度は百倍、数回のプロセスよりも速く、非常に高速です。
    3. プロセス同じデータは、プロセス間通信のプロセスおよび方法によって必要なスレッドとスレッド、キュー、などの間で共有することができます。
  3. スレッド・アプリケーション

    同時実行:CPUは、複数のタスクの同時実行のように見えます

    3つのスレッド、同時タスクを開くには、単一のプロセス。

    三つのプロセスに並行タスクを開きます。

    オープンマルチスレッドの利点:データ共有、小さなオーバーヘッド、速いです。

メインスレッドと子は、それらの間の区別をしないスレッド

だから、プロセスの作業で誰ですか?

メインスレッドは、コードの実行を終了したときの作業でメインスレッドは、プロセスから撤退するために実行する他のスレッドを待つ必要があります。

2つの方法で3. [スレッド

**スレッド必要としない場合に_ _名前_ _ == '_ _メイン_ _':次の文**

最初:

from threading import Thread
import time

def task(name):
    print(f"{name} is running")
    time.sleep(1)
    print(f"{name} is gone")


if __name__ == '__main__':
    t1 = Thread(target=task,args=("zcy",))
    t1.start()
    print("==main Threading==") # 线程没有主次之分

第二:

from threading import Thread
import time

class MyThread(Thread):

    def __init__(self,name,lst,s):
        super(MyThread, self).__init__()
        self.name = name
        self.lst =lst
        self.s = s

    def run(self):
        print(f"{self.name} is running")
        time.sleep(1)
        print(f"{self.name} is gone")

if __name__ == '__main__':
    t1 = MyThread("zdr",[1,2,3],"180")
    t1.start()
    print("==main thread==")

プロセスVSコードスレッドの4比較

  1. オープン速度比較

    # 多进程
    from multiprocessing import Process
    
    def work():
        print('hello')
    
    def task():
        print('bye')
    
    if __name__ == '__main__':
        # 在主进程下开启线程
        t1 = Process(target=work)
        t2 = Process(target=task)
        t1.start()
        t2.start()
        print('main thread/process')
    # 多线程
    from threading import Thread
    import time
    
    def task(name):
        print(f"{name} is running")
        time.sleep(1)
        print(f"{name} is gone")
    
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task,args=("zdr",))
        t2 = Thread(target=task,args=("zcy",))
        t3 = Thread(target=task,args=("zfy",))
        t4 = Thread(target=task,args=("lfz",))
        t1.start()
        t2.start()
        t3.start()
        t4.start()
        print('==main thread==') # 线程是没有主次之分
  2. コントラストPID

    # 进程
    from multiprocessing import Process
    import time
    import os
    
    def task():
        print(f"子进程:{os.getpid()}")
        print(f"主进程:{os.getppid()}")
    
    
    if __name__ == '__main__':
        p1 = Process(target=task)
        p2 = Process(target=task)
        p1.start()
        p2.start()
    
        print(f"==main{os.getpid()}")
    # 主线程
    from threading import Thread
    import os
    
    def task():
        print(os.getpid())
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task)
        t2 = Thread(target=task)
        t1.start()
        t2.start()
        print(f"===main thread:{os.getpid()}")
  3. スレッドは、同じプロセス内の内部データを共有します

    from threading import Thread
    import os
    
    
    x = 3
    def task():
        global x
        x = 100
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task)
        t1.start()
        print(f"===main thread:{x}")
    
    
    # 同一个进程内的资源数据对于这个进程的多个线程来说是共享的.

小演習:

import multiprocessing
import threading

import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('127.0.0.1',8080))
s.listen(5)

def action(conn):
    while True:
        data=conn.recv(1024)
        print(data)
        conn.send(data.upper())

if __name__ == '__main__':

    while True:
        conn,addr=s.accept()


        p=threading.Thread(target=action,args=(conn,))
        p.start()

多线程并发的socket服务端
import socket

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('127.0.0.1',8080))

while True:
    msg=input('>>: ').strip()
    if not msg:continue

    s.send(msg.encode('utf-8'))
    data=s.recv(1024)
    print(data)

客户端

5.その他の関連するスレッド

Threadオブジェクト:

.isAlive()#スレッドスレッドが生きているかどうかを判断します

スレッド.getname()#は、スレッド名を取得します。

スレッド.setname()#はスレッド名を設定します***

threadingモジュールの方法:

threading.currentThread()#は、現在のプロセスのオブジェクトを取得します

threading.enumerate()#すべてのスレッドオブジェクトのリストを返します。

threading.activeCount()#はまだ生きているスレッドの数を示す数値を返します。

from threading import Thread, currentThread, enumerate,activeCount
import os
import time

x = 3
def task():
    # print(currentThread())
    # time.sleep(1)
    print("123")


if __name__ == '__main__':
    t1 = Thread(target=task,name="xc-1")
    t2 = Thread(target=task,name="xc-2")
    # name 设置线程名
    t1.start()
    t2.start()
    # time.sleep(2)
    # print(t1.isAlive()) # 判断线程是否存活
    # print(t1.getName()) # 获取线程名
    # t1.setName("zcy-01")
    # print(t1.name)      # ***



    # threading方法
    # print(currentThread())     # 获取当前线程的对象
    # print(currentThread().name)     # 获取当前线程的对象
    print(enumerate())      # 返回一个列表,包含所有的线程对象
    print(activeCount())
    print(f"===main thread:{os.getpid()}")

6.joinとデーモンスレッド

そして、子スレッドが終了するのを待つためにメインスレッドに通知するためにメインスレッドをブロックした後に実行します。参加

# 线程join
from threading import Thread
import time

def task(name):
    print(f"{name} is running")
    time.sleep(1)
    print(f'{name} is gone')


if __name__ == '__main__':
    start_time = time.time()
    t1 = Thread(target=task,args=("zdr",))
    t2 = Thread(target=task,args=("zcy",))
    t3 = Thread(target=task,args=("zfy",))

    t1.start()
    t1.join()
    t2.start()
    t2.join()
    t3.start()
    t3.join()

    print(f"===main thread:{time.time() - start_time}")

デーモンスレッド:

それは、プロセスまたはスレッドであるかどうか、次のとおりです。メインの実行が破壊した後に終了するためにガーディアンxxxのxxxは待機します

終了を実行し終えていない:ことが強調されます

#1.对主进程来说,运行完毕指的是主进程代码运行完毕

#2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕

詳細説明:

#1 主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束,

#2 主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。

デーモンを比較するには:

from multiprocessing import Process
import time

def foo():
    print(123)
    time.sleep(1)
    print("end123")



def bar():
    print(456)
    time.sleep(2)
    print("end456")


if __name__ == '__main__':
    p1 = Process(target=foo)
    p2 = Process(target=bar)

    p1.daemon = True
    p1.start()
    p2.start()
    print('====main====')

デーモンスレッド:

from threading import Thread
import time


def sayhi(name):
    print('bye~')
    time.sleep(2)
    print(f'{name} say hello ')


if __name__ == '__main__':
    t = Thread(target=sayhi,args=('zcy',))
    # t.setDaemon(True)
    t.daemon = True
    t.start()

    print('主线程')
from threading import Thread
import time


def foo():
    print(123)  # 1
    time.sleep(1)
    print('end123') # 4


def bar():
    print(456)  # 2
    time.sleep(3)
    print('en456')  # 3


t1 = Thread(target=foo)
t2 = Thread(target=bar)


t1.daemon = True
t1.start()
t2.start()
print('=====main====')  # 3



结果:
123
456
=====main====
end123
en456   

# 主线程什么时候结束?
# 主线程等待非守护子线程结束之后,结束
from threading import Thread
import time

def foo():
    print(123)  # 1
    time.sleep(3)
    print("end123")  

def bar():
    print(456)   # 2
    time.sleep(1)
    print("end456")  # 4


t1=Thread(target=foo)
t2=Thread(target=bar)

t1.daemon=True
t1.start()
t2.start()
print("main-------")  # 3


结果:
123
456
main-------
end456

7.ミューテックス

from threading import Thread
import time
import random

x = 100

def task():
    time.sleep(random.randint(1,2))
    global x
    temp = x
    time.sleep(random.randint(1,3))
    temp = temp - 1
    x = temp


if __name__ == '__main__':
    l = []
    for i in range(100):
        t = Thread(target=task)
        l.append(t)
        t.start()

    for i in l:
        i.join()

    print(f"main:{x}")
    
    
    
    
# 多个任务共抢一个数据,要保证数据的安全性,要让他们串行
# 给线程加锁
from threading import Thread
from threading import Lock
import time
import random
x = 100

def task(lock):

    lock.acquire()
    # time.sleep(random.randint(1,2))
    global x
    temp = x
    time.sleep(0.01)
    temp = temp - 1
    x = temp
    lock.release()


if __name__ == '__main__':
    mutex = Lock()
    l1 = []
    for i in range(100):
        t = Thread(target=task,args=(mutex,))
        l1.append(t)
        t.start()

    time.sleep(3)
    print(f'主线程{x}')

おすすめ

転載: www.cnblogs.com/zhangchaoyin/p/11415382.html