程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

python 多線程篇

編輯:Python

文章目錄

  • 線程
  • 多線程

本文將會介紹 Python 編程語言中多線程處理的基礎知識。就像多處理一樣,多線程是實現多任務處理的一種方式。在多線程處理中,使用 線程的概念。

讓我們首先了解計算機體系結構中線程的概念。

線程

在計算中,進程是正在執行的計算機程序的實例。任何過程都有 3 個基本組件:

  • 可執行程序。
  • 程序所需的關聯數據(變量、工作空間、緩沖區等)
  • 程序的執行上下文(進程狀態)

線程是進程中可以安排執行的實體。此外,它是可以在操作系統(操作系統)中執行的最小處理單元。

簡單來說,線程是程序中可以獨立於其他代碼執行的此類指令序列。為簡單起見,您可以假設線程只是進程的子集!

線程在線程控制塊 (TCB) 中包含所有這些信息:

  • 線程標識符: 將唯一 ID (TID) 分配給每個新線程
  • 堆棧指針: 指向進程中的線程堆棧。堆棧包含線程作用域下的局部變量。
  • 程序計數器: 存儲線程當前正在執行的指令地址的寄存器。
  • 線程狀態: 可以是正在運行、就緒、等待、啟動或完成。
  • 線程的寄存器集: 分配給線程進行計算的寄存器。
  • 父進程指針: 指向線程所在的進程的過程控制塊 (PCB) 的指針。

請參考下圖以了解進程與其線程之間的關系:

多線程

一個進程中可以存在多個線程,其中:

  • 每個線程都包含自己的寄存器集局部變量(存儲在堆棧中)。
  • 進程的所有線程共享全局變量(存儲在堆中)程序代碼

請參考下圖以了解內存中如何存在多個線程:

在Python中,線程模塊提供了一個非常簡單直觀的API,用於在程序中生成多個線程。

讓我們考慮一個使用線程模塊的簡單示例:

import threading
def print_cube(num):
"""用於打印給定數字的多維數據集的函數"""
print("Cube: {}".format(num * num * num))
def print_square(num):
"""函數打印給定數值的平方"""
print("Square: {}".format(num * num))
if __name__ == "__main__":
# 創建線程
t1 = threading.Thread(target=print_square, args=(10,))
t2 = threading.Thread(target=print_cube, args=(10,))
# 啟動線程1
t1.start()
# 啟動線程2
t2.start()
# 等待線程1完全執行
t1.join()
# 等待線程2完全執行
t2.join()
# 兩個線程都已完全執行
print("Done!")

運行結果:

讓我們試著理解上面的代碼:

  • 要導入線程模塊,我們需要:

    import threading
    
  • 要創建一個新線程,我們創建一個 Thread 類的對象。它需要以下參數:

    • 目標:線程要執行的函數
    • args:要傳遞給目標函數的參數

    在上面的例子中,我們創建了2個具有不同目標函數的線程:

    t1 = threading.Thread(target=print_square, args=(10,))
    t2 = threading.Thread(target=print_cube, args=(10,))
    
  • 要啟動線程,我們使用 Thread 類的 start 方法。

    t1.start()
    t2.start()
    
  • 一旦線程啟動,當前程序(你可以把它想象成一個主線程)也會繼續執行。為了停止當前程序的執行,直到線程完成,我們使用連接方法。

    t1.join()
    t2.join()
    

    因此,當前程序將首先等待 t1 的完成,然後等待 t2 完成。完成後,將執行當前程序的其余語句。

考慮下圖,以更好地了解上述程序的工作原理:

考慮下面給出的python程序,其中我們為每個任務打印線程名稱和相應的進程:

import threading
import os
def task1():
print("任務1分配給線程: {}".format(threading.current_thread().name))
print("運行任務1的進程ID: {}".format(os.getpid()))
def task2():
print("任務2分配給線程: {}".format(threading.current_thread().name))
print("運行任務2的進程ID: {}".format(os.getpid()))
if __name__ == "__main__":
# 打印當前進程的ID
print("運行主程序的進程ID: {}".format(os.getpid()))
# 打印主線程名稱
print("主線程名稱: {}".format(threading.current_thread().name))
# 創建線程
t1 = threading.Thread(target=task1, name='t1')
t2 = threading.Thread(target=task2, name='t2')
# 啟動線程
t1.start()
t2.start()
# 等待所有線程完成
t1.join()
t2.join()

運行結果:

讓我們試著理解上面的代碼:

  • 我們使用 os.getpid() 函數來獲取當前進程的 ID。

    print("運行主程序的進程ID: {}".format(os.getpid()))
    

    從輸出中可以清楚地看出,所有線程的進程 ID 都保持不變。

  • 我們使用threading.main_thread() 函數來獲取主線程對象。在正常情況下,主線程是啟動Python解釋器的線程。線程對象的 name 屬性用於獲取線程的名稱。

    print("主線程名稱: {}".format(threading.main_thread().name))
    
  • 我們使用 threading.current_thread() 函數來獲取當前線程對象。

    print("任務1分配的線程: {}".format(threading.current_thread().name))
    

下圖闡明了上述概念:


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved