Python 多線程教程|Python 主題月

本文正在參加「Python主題月」,詳情查看 活動連接python

在這個 Python 多線程教程中,您將看到建立線程的不一樣方法,並學習實現線程安全操做的同步。這篇文章的每一個部分都包含一個示例和示例代碼,以逐步解釋該概念。git

順便說一下,多線程是幾乎全部高級編程語言都支持的軟件編程的核心概念。所以,您應該知道的第一件事是:什麼是線程以及多線程在計算機科學中意味着什麼。github

什麼是計算機科學中的線程?

在軟件編程中,線程是具備獨立指令集的最小執行單元。它是進程的一部分,並在共享程序的可運行資源(如內存)的相同上下文中運行。一個線程有一個起點、一個執行順序和一個結果。它有一個指令指針,用於保存線程的當前狀態並控制接下來按什麼順序執行。面試

什麼是計算機科學中的多線程?

一個進程並行執行多個線程的能力稱爲多線程。理想狀況下,多線程能夠顯着提升任何程序的性能。並且 Python 多線程機制很是人性化,您能夠快速學習。編程

多線程的優勢

  • 多線程能夠顯着提升多處理器或多核系統的計算速度,由於每一個處理器或核同時處理一個單獨的線程。
  • 多線程容許程序在一個線程等待輸入時保持響應,同時另外一個線程運行 GUI。此陳述適用於多處理器或單處理器系統。
  • 進程的全部線程均可以訪問其全局變量。若是一個全局變量在一個線程中發生變化,那麼它對其餘線程也是可見的。線程也能夠有本身的局部變量。

多線程的缺點

  • 在單處理器系統上,多線程不會影響計算速度。因爲管理線程的開銷,性能可能會降低。
  • 訪問共享資源時須要同步以防止互斥。它直接致使更多的內存和 CPU 利用率。
  • 多線程增長了程序的複雜性,從而也使得調試變得困難。
  • 它增長了潛在死鎖的可能性。
  • 當線程沒法按期訪問共享資源時,它可能會致使飢餓。應用程序將沒法恢復其工做。

到目前爲止,您已經閱讀了有關線程的理論概念。若是您不熟悉 Python,咱們建議您閱讀咱們的 30 個快速 Python 編碼技巧,它們也能夠幫助您編寫 Python 多線程代碼。咱們的許多讀者都使用了這些技巧,而且可以提升他們的編碼技能。安全

Python 多線程模塊

Python 提供了兩個模塊來在程序中實現線程。markdown

  • ** **模塊和
  • **<線程> **模塊。

注意:供您參考,Python 2.x 曾經有 < thread> 模塊。但它在 Python 3.x 中被棄用並重命名爲 <  _thread> 模塊以實現向後兼容性。數據結構

兩個模塊的主要區別在於模塊<_線程>將線程實現爲函數。另外一方面,< threading >模塊提供了一種面向對象的方法來啓用線程建立。多線程

如何使用線程模塊建立線程?

若是你決定在你的程序中應用< thread > 模塊,那麼使用下面的方法來產生線程。app

#語法

thread.start_new_thread ( function, args[, kwargs] )
複製代碼

這種方法對於建立線程很是有效和直接。您可使用它在 Linux 和 Windows 中運行程序。

此方法啓動一個新線程並返回其標識符。它將使用傳遞的參數列表調用指定爲「函數」參數的函數。當 < function > 返回時,線程將靜默退出。

這裏,args是一個參數元組;使用空元組調用 < function > 不帶任何參數。可選的 < kwargs > 參數指定關鍵字參數的字典。

**若是 < function > 因未處理的異常而終止,則會打印堆棧跟蹤,而後線程退出(它不會影響其餘線程,它們會繼續運行)。使用如下代碼瞭解有關線程的更多信息。

基本的 Python 多線程示例

#Python 多線程示例。
#1. 使用遞歸計算階乘。
#2. 使用線程調用階乘函數。

from _thread import start_new_thread
from time import sleep

threadId = 1 #線程計數器
waiting = 2 #2秒等待的時間

def factorial(n):
    global threadId
    rc = 0
    
    if n < 1:   # base case
        print("{}: {}".format('\nThread', threadId ))
        threadId += 1
        rc = 1
    else:
        returnNumber = n * factorial( n - 1 )  # recursive call
        print("{} != {}".format(str(n), str(returnNumber)))
        rc = returnNumber
    
    return rc

start_new_thread(factorial, (5, ))
start_new_thread(factorial, (4, ))

print("Waiting for threads to return...")
sleep(waiting)
複製代碼

您能夠在本地 Python 終端中運行上述代碼,也可使用任何在線 Python 終端。執行此程序後,它將產生如下輸出。

程序輸出

# Python 多線程:程序輸出-
等待線程返回...

Thread: 1
1 != 1
2 != 2
3 != 6
4 != 24
5 != 120

Thread: 2
1 != 1
2 != 2
3 != 6
4 != 24
複製代碼

如何使用線程模塊建立線程?

最新的< threading >模塊比上一節討論的遺留< thread >模塊提供了豐富的特性和更好的線程支持。< threading > 模塊是 Python 多線程的一個很好的例子。

threading > 模塊結合了 < thread > 模塊的全部方法,並暴露了一些額外的方法

  • threading.activeCount(): 它找到總數。活動線程對象。
  • threading.currentThread(): 您可使用它來肯定調用方線程控制中的線程對象數量。
  • threading.enumerate(): 它將爲您提供當前活動的線程對象的完整列表。

除了上述方法,< threading >模塊還提供了< Thread >類,你能夠嘗試實現線程。它是 Python 多線程的面向對象的變體。

Thread > 類發佈如下方法。

類方法 方法說明
run(): 它是任何線程的入口點函數。
start(): start() 方法在 run 方法被調用時觸發一個線程。
join([time]): join() 方法使程序可以等待線程終止。
isAlive(): isAlive() 方法驗證活動線程。
getName(): getName() 方法檢索線程的名稱。
setName(): setName() 方法更新線程的名稱。

使用線程模塊實現線程的步驟

您能夠按照如下步驟使用 < threading > 模塊實現一個新線程。

  • 從 < Thread > 類構造一個子類。
  • 覆蓋 <  init(self [,args])  > 方法以根據要求提供參數。
  • 接下來,重寫< run(self [,args])  > 方法來編寫線程的業務邏輯。

一旦定義了新的 < Thread> 子類,就必須實例化它以啓動一個新線程。而後,調用 < start()> 方法來啓動它。它最終會調用< run()> 方法來執行業務邏輯。

示例 – 建立一個線程類來打印日期

#Python 多線程示例打印當前日期。
#1. 使用 threading.Thread 類定義子類。
#2. 實例化子類並觸發線程。

import threading
import datetime

class myThread (threading.Thread):
    def __init__(self, name, counter):
        threading.Thread.__init__(self)
        self.threadID = counter
        self.name = name
        self.counter = counter
    def run(self):
        print("\nStarting " + self.name)
        print_date(self.name, self.counter)
        print("Exiting " + self.name)

def print_date(threadName, counter):
    datefields = []
    today = datetime.date.today()
    datefields.append(today)
    print("{}[{}]: {}".format( threadName, counter, datefields[0] ))

# 建立新線程
thread1 = myThread("Thread", 1)
thread2 = myThread("Thread", 2)

# 啓動新線程
thread1.start()
thread2.start()

thread1.join()
thread2.join()
print("\nExiting the Program!!!")
複製代碼

程序輸出

Starting Thread
Thread[1]: 2021-07-22
Exiting Thread

Starting Thread
Thread[2]: 2021-07-22
Exiting Thread

Exiting the Program!!!
複製代碼

Python 多線程——同步線程

threading > 模塊具備實現鎖定的內置功能,容許您同步線程。須要鎖定來控制對共享資源的訪問,以防止損壞或丟失數據。

您能夠調用 Lock() 方法來應用鎖,它返回新的鎖對象。而後,您能夠調用鎖對象的獲取(阻塞) 方法來強制線程同步運行。

可選的阻塞參數指定線程是否等待獲取鎖。

  • Case Blocking = 0:若是獲取鎖失敗,線程將當即返回零值,若是鎖成功則返回一。
  • Case Blocking = 1:線程阻塞並等待鎖被釋放。

鎖對象的release() 方法用於在再也不須要時釋放鎖。

僅供參考,Python 的內置數據結構(例如列表、字典)是線程安全的,由於它具備用於操做它們的原子字節碼的反作用。在 Python 中實現的其餘數據結構或基本類型(如整數和浮點數)沒有這種保護。爲了防止同時訪問一個對象,咱們使用了一個Lock 對象。

鎖定的多線程示例

#Python 多線程示例來演示鎖定。
#1. 使用 threading.Thread 類定義子類。
#2. 實例化子類並觸發線程。
#3. 在線程的 run 方法中實現鎖。

import threading
import datetime

exitFlag = 0

class myThread (threading.Thread):
    def __init__(self, name, counter):
        threading.Thread.__init__(self)
        self.threadID = counter
        self.name = name
        self.counter = counter
    def run(self):
        print("\nStarting " + self.name)
        # 獲取鎖同步線程
        threadLock.acquire()
        print_date(self.name, self.counter)
        # 爲下一個線程釋放鎖
        threadLock.release()
        print("Exiting " + self.name)

def print_date(threadName, counter):
    datefields = []
    today = datetime.date.today()
    datefields.append(today)
    print("{}[{}]: {}".format( threadName, counter, datefields[0] ))

threadLock = threading.Lock()
threads = []

# 建立新線程
thread1 = myThread("Thread", 1)
thread2 = myThread("Thread", 2)

# 啓動新線程
thread1.start()
thread2.start()

# 添加線程到線程列表
threads.append(thread1)
threads.append(thread2)

# 等待全部線程完成
for thread in threads:
    thread.join()

print("\nExiting the Program!!!")
複製代碼

程序輸出

Starting Thread
Thread[1]: 2021-07-22
Exiting Thread

Starting Thread
Thread[2]: 2021-07-22
Exiting Thread

Exiting the Program!!!
複製代碼

總結——初學者的 Python 多線程

我但願您會發現這個 Python 多線程教程很是有趣且引人入勝。若是您喜歡這篇文章並有興趣看到更多此類文章,能夠看看這裏(Github/Gitee) 關注我以查看更多信息,這裏彙總了個人所有原創及做品源碼

🧵 更多相關文章

往日優秀文章推薦:

若是你真的從這篇文章中學到了一些新東西,喜歡它,收藏它並與你的小夥伴分享。🤗最後,不要忘了❤或📑支持一下哦

相關文章
相關標籤/搜索