本文正在參加「Python主題月」,詳情查看 活動連接python
在這個 Python 多線程教程中,您將看到建立線程的不一樣方法,並學習實現線程安全操做的同步。這篇文章的每一個部分都包含一個示例和示例代碼,以逐步解釋該概念。git
順便說一下,多線程是幾乎全部高級編程語言都支持的軟件編程的核心概念。所以,您應該知道的第一件事是:什麼是線程以及多線程在計算機科學中意味着什麼。github
在軟件編程中,線程是具備獨立指令集的最小執行單元。它是進程的一部分,並在共享程序的可運行資源(如內存)的相同上下文中運行。一個線程有一個起點、一個執行順序和一個結果。它有一個指令指針,用於保存線程的當前狀態並控制接下來按什麼順序執行。面試
一個進程並行執行多個線程的能力稱爲多線程。理想狀況下,多線程能夠顯着提升任何程序的性能。並且 Python 多線程機制很是人性化,您能夠快速學習。編程
到目前爲止,您已經閱讀了有關線程的理論概念。若是您不熟悉 Python,咱們建議您閱讀咱們的 30 個快速 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 多線程示例。
#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 >模塊還提供了< Thread >類,你能夠嘗試實現線程。它是 Python 多線程的面向對象的變體。
< Thread > 類發佈如下方法。
類方法 | 方法說明 |
---|---|
run(): | 它是任何線程的入口點函數。 |
start(): | start() 方法在 run 方法被調用時觸發一個線程。 |
join([time]): | join() 方法使程序可以等待線程終止。 |
isAlive(): | isAlive() 方法驗證活動線程。 |
getName(): | getName() 方法檢索線程的名稱。 |
setName(): | setName() 方法更新線程的名稱。 |
您能夠按照如下步驟使用 < threading > 模塊實現一個新線程。
一旦定義了新的 < 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!!!
複製代碼
< threading > 模塊具備實現鎖定的內置功能,容許您同步線程。須要鎖定來控制對共享資源的訪問,以防止損壞或丟失數據。
您能夠調用 Lock() 方法來應用鎖,它返回新的鎖對象。而後,您能夠調用鎖對象的獲取(阻塞) 方法來強制線程同步運行。
可選的阻塞參數指定線程是否等待獲取鎖。
鎖對象的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 多線程教程很是有趣且引人入勝。若是您喜歡這篇文章並有興趣看到更多此類文章,能夠看看這裏(Github/Gitee) 關注我以查看更多信息,這裏彙總了個人所有原創及做品源碼
往日優秀文章推薦:
若是你真的從這篇文章中學到了一些新東西,喜歡它,收藏它並與你的小夥伴分享。🤗最後,不要忘了❤或📑支持一下哦