前言
我們知道,每個獨立的進程有一個程序運行的入口、順序執行序列和程序的出口。進程里面的任務由線程執行,線程必須依存在應用程序中,多個線程執行能夠提高應用程序的執行效率,多個線程之間共用進程的寄存器數據和堆棧等等。
python多線程 類似于同時執行多個不同程序 ,具有以下特點:
1、用戶界面可以更加吸引人,這樣比如用戶點擊了一個按鈕去觸發某些事件的處理,可以彈出一個進度條來顯示處理的進度
程序的運行速度可能加快
2、在一些等待的任務實現上如用戶輸入、文件讀寫和網絡收發數據等,線程就比較有用了。在這種情況下我們可以釋放一些珍貴的資源如內存占用等等。
?
一、python使用多線程
Python中使用線程有兩種方式: _thread模塊 函數或者用 threading 模塊 封裝類來使用線程對象。
1、_thread模塊函數方式:
_thread.start_new_thread ( function, args[, kwargs] )
注:原本的thread 模塊已被廢棄。所以,在 Python3 中不能再使用"thread" 模塊。為了兼容性,Python3 將 thread 重命名為 "_thread"。在此推薦使用第二種模塊封裝的方式:threading 模塊。
?
2、threading 模塊封裝:
threading 模塊除了包含 _thread 模塊中的所有方法外,還提供的其他方法:
threading.currentThread(): 返回當前的線程變量。
threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啟動后、結束前,不包括啟動前和終止后的線程。
threading.activeCount(): 返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。
除了使用方法外,線程模塊同樣提供了Thread類來處理線程,Thread類提供了以下方法:
使用 threading 模塊創建線程:
#!/usr/bin/python3
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print ("開始線程:" + self.name)
print_time(self.name, self.counter, 5)
print ("退出線程:" + self.name)
def print_time(threadName, delay, counter):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print ("%s: %s" % (threadName, time.ctime(time.time())))
counter -= 1
# 創建新線程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 開啟新線程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("退出主線程")
二、線程同步問題
和Java的多線程一樣,Python多線程也要處理線程同步問題,如果多個線程共同對某個數據修改,則在數據的正確性和一致性方面可能出現不可預料的結果。
使用 Thread 對象的鎖機制 可以實現簡單的線程同步,這兩個對象都有 acquire 方法和 release 方法,對于那些需要每次只允許一個線程操作的數據,可以將其操作放到 acquire 和 release 方法 之間。如下:
鎖有兩種狀態——鎖定和未鎖定。每當一個線程要訪問共享數據時,必須先獲得鎖定;如果已經有別的線程獲得鎖定了,那么就讓當前線程暫停,也就是同步阻塞;等到鎖定的線程訪問完畢,釋放鎖以后,再讓當前線程繼續。
#!/usr/bin/python3
import threading
import time
class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print ("開啟線程: " + self.name)
# 獲取鎖,用于線程同步
threadLock.acquire()
print_time(self.name, self.counter, 3)
# 釋放鎖,開啟下一個線程
threadLock.release()
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print ("%s: %s" % (threadName, time.ctime(time.time())))
counter -= 1
threadLock = threading.Lock()
# 創建新線程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 開啟新線程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("退出主線程")
以上程序輸出結果就是同步阻塞的:
開啟線程: Thread-1
開啟線程: Thread-2
Thread-1: Wed Apr 6 11:52:57 2016
Thread-1: Wed Apr 6 11:52:58 2016
Thread-1: Wed Apr 6 11:52:59 2016
Thread-2: Wed Apr 6 11:53:01 2016
Thread-2: Wed Apr 6 11:53:03 2016
Thread-2: Wed Apr 6 11:53:05 2016
退出主線程
三、python多線程的局限性
與PHP一樣,腳本解釋性的語言都需要一個解析器,一邊解析一邊運行程序,PHP中通常使用CGI、Fast-CGI協議解析器來解釋PHP語言,python也有多種解析器,可以讓python在多種環境下(如CPython解析器,PyPy,Psyco)執行,通常默認的也就是用的最多的是CPython解析器, CPython實現了PHP的解析器沒有實現的多線程環境 ,能對多線程進行調度管理。
但是,CPython里面就算開了多個線程環境, CPython解釋器也只能一個一個地解釋Python語言來運行 ,這是因為Python解釋器CPython采用了 全局解釋器鎖(GIL) 的機制,所以多線程實質上也是由當個解釋器逐一解釋運行,沒辦法做到真正的并行。
關于Python的全局解釋器鎖(GIL)的機制,將會在接下來的文章中詳細介紹。
本文參考鏈接:https://www.runoob.com/python3/python3-multithreading.html
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
