原載於
而一般的python**執行起來只有乙個程序,所有的語句都是順序執行的。這樣就會很浪費時間。如果有三個操作分別耗時t1,t2,t3,那麼順序執行的時間將會是sum(t1,t2,t3)。如果它們能夠並行執行的話,花費的時間將會是max(t1,t2,t3)。
python提供了執行緒類,在乙個python程序內可以建立多個執行緒,可並行執行多個執行緒。
16.1 執行緒建立和使用
python的執行緒建立有兩種方式,一種通過引數例項化threading.thread類;另外一種是自己繼承threading.thread類,重寫__init__()和run()方法。
先來介紹使用引數例項化乙個threading.thread類。這種方法很簡潔,是推薦的方法。
threading.thread類的例項化需要幾個引數,其中target引數需要傳入乙個可執行的物件,可以是乙個函式,也可以是乙個可執行檔案;而name引數是執行緒的名字;args引數是target物件的引數元組,如果target是乙個函式的話,那麼args需要傳入這個函式的引數;kwargs是target物件的字典引數。
下面我們先定乙個函式,用於作為執行緒的可執行物件。這段**的作用是,隨機生成乙個0到5秒的數字,並且延遲這個隨機時間。如果生成3,那麼就延遲3秒。然後列印出傳入的執行緒名和延遲描述。
def randnum(threadname):a=random.randint(0,5)
time.sleep(a)
print(threadname+" sleep "+str(a))
from threading import threadt=thread(target=randnum,name=threadname,args=(threadname,))
thread例項化後並不會啟動執行乙個執行緒,需要使用start()方法執行緒才會啟動執行。使用join()方法可以等待乙個執行緒的結束。可能是正常結束或者出現異常而結束。
一段完整的**如下
from threading import threadimport random
import time
def randnum(threadname):
a=random.randint(0,5)
time.sleep(a)
print(threadname+" sleep "+str(a))
starttime=time.time()
threadlist=
for i in range(5):
threadname="thread"+str(i)
t=thread(target=randnum,name=threadname,args=(threadname,))
t.start()
for t in threadlist:
t.join()
endtime=time.time()
print('total time :'+ str(endtime-starttime))
乙個可能的執行結果是
thread0 sleep 2thread1 sleep 2
thread4 sleep 3
thread3 sleep 5
thread2 sleep 5
total time :5.00261211395
下面來介紹另外一種使用執行緒的方法。需要自己繼承執行緒類,並且重寫__init__()方法以及run()方法。因為使用執行緒物件的start()來啟動乙個執行緒的時候,start()方法實際上會呼叫run()方法。
我們先來看看**
class mythread(thread):def __init__(self,threadname):
thread.__init__(self)
self.threadname=threadname
def run(self):
self.randnum(self.threadname)
def randnum(self,threadname):
a=random.randint(0,5)
time.sleep(a)
print(threadname+" sleep "+str(a))
在這段**裡面randnum函式作為類的乙個方法出現,實際上它也可以是乙個外部函式,或者乙個可執行檔案的語句。
run()方法的作用是呼叫了randnum函式。
此時初始化這個執行緒類的語句就很簡單了,因為我們在定義類的時候已經封裝得很好了。
t=mythread(threadname)
from threading import threadimport random
import time
class mythread(thread):
def __init__(self,threadname):
thread.__init__(self)
self.threadname=threadname
def run(self):
self.randnum(self.threadname)
def randnum(self,threadname):
a=random.randint(0,5)
time.sleep(a)
print(threadname+" sleep "+str(a))
starttime=time.time()
threadlist=
for i in range(5):
threadname="thread"+str(i)
t=mythread(threadname)
t.start()
for t in threadlist:
t.join()
endtime=time.time()
print('total time :'+ str(endtime-starttime))
如果想要啟動乙個執行緒,讓它在python退出之後也存在,那麼可以通過thread的setdaemon()來進行設定。
在某些機器上面不支援thread類,那麼可以使用dummy_thread類。這個類不是python內部實現的,是乙個c語言的外部類,因此無法檢測它的狀態。無法對它進行join()。
python的thread類只能夠在乙個cpu核執行,因為python程序鎖的關係。如果要盡多核能力,可以使用multiprocessing類,它可以平衡多核cpu的使用。
執行緒的使用還有很多內容。這個涉及到了作業系統部分的內容。
比如多個執行緒之間可能訪問同乙個資源,比如同乙個檔案,資料庫的同一塊資料等等。此時在同乙個時間可能有多個執行緒進行資料的讀寫,但是資料的儲存空間只有乙個,在這裡就需要多個執行緒排隊訪問了。這需要乙個鎖來控制線程的訪問。這就是執行緒鎖的概念。
比如多個執行緒之間可能需要通訊,乙個執行緒執行完了,可能需要喚起另外乙個執行緒,這個又涉及到了執行緒之間通訊的問題。有時候執行緒a需要等執行緒b的喚起,而執行緒b需要等待執行緒c的喚起,執行緒c又需要等待執行緒a的喚起。這個時候就形成了死鎖。每個執行緒都在等待,無法進行下一步。
這些內容在threading類當中都有體現,但是這裡不進行**。
Matlab之代數方程求解 極限 漸進線 導數
matlab之代數方程求解 極限 漸進線 導數 目錄 極限 漸進線 導數 1 求趨於常量的極限 2 利用limit f,inf 命令無窮極限 3 獲得漸進線 4 導數計算 1 案例limit f 命令屬於符號計算,因此確保使用syms 命令告訴matlab你使用的是哪個符號變數。syms x f 2...
進 執行緒死鎖產生的原因
執行緒死鎖產生的必要條件 1 互斥條件 乙個資源每次只能被乙個程序使用。2 請求與保持條件 乙個程序因請求資源而阻塞時,對已獲得的資源保持不放。3 不可剝奪條件 程序已獲得的資源,在末使用完之前,不能強行剝奪。4 迴圈等待條件 若干程序之間形成一種頭尾相接的迴圈等待資源關係。1 等待某個資源時,使用...
進執行緒通訊之有名訊號量
有名訊號量 semphore 如果說訊號是外部事件和程序的關聯的機制的話,那麼訊號量就是程序 執行緒之間通訊的機制。根據是支援不同程序之間的通訊還是同乙個程序內不同執行緒的通訊,訊號量可以分為有名訊號量和無名訊號量。顧名思義,有名訊號量在建立起來時需要顯式地指名乙個訊號量的名字,在linux這個名字...