Python多線程實例教程
本文以實例形式較為詳細的講解了Python的多線程,是Python程序設計中非常重要的知識點。分享給大家供大家參考之用。具體方法如下:
用過Python的人都會覺得Python的多線程很類似于Java的多線程機制,但是比JAVA的多線程更靈活。在早期的Python多線程實現(xiàn)中,采用了thread模塊。例如:
from time import ctime,sleep from thread import start_new_thread def loop1(): print "enter loop1:",ctime(); sleep(3); print "leave loop1:",ctime(); def loop2(): print "enter loop2:",ctime(); sleep(5); print "leave loop2:",ctime(); def main(): print "main begin:",ctime(); start_new_thread(loop1, ()); start_new_thread(loop2,()); sleep(8); print "main end:",ctime(); if __name__=="__main__": main();
簡單介紹下這個代碼塊中的函數(shù)功能,sleep是線程睡眠時間,幾乎等價于JAVA中的Thread.sleep(millionseconds)
start_new_thread是實例化一個線程并運行的方法,方法的第一個參數(shù)接受一個線程運行時所執(zhí)行的函數(shù)對象,第二個參數(shù)是方法執(zhí)行時所需要的參數(shù),以一個元組的形式傳入。
這大概是最早期的Python多線程實現(xiàn)了,注意代碼中的main線程里的sleep(8)。這里的睡眠時間只能比3+5大,而不能小。如果小于這個時間,那么main主線程會提前退出,導致無論其子線程是否是后臺線程,都將會中斷,從而拋出線程中斷異常,類似于Java的ThreadInterruptException。這個致命的影響幾乎就是這個模塊后期被拋棄的罪魁禍首。
當然在早期的Python多線程中,你可以利用加鎖的機制來避免出現(xiàn)這個情況。稍微改動下以上代碼:
import thread;
from time import sleep,ctime;
from random import choice
#The first param means the thread number
#The second param means how long it sleep
#The third param means the Lock
def loop(nloop,sec,lock):
print "Thread ",nloop," start and will sleep ",sec;
sleep(sec);
print "Thread ",nloop," end ",sec;
lock.release();
def main():
seconds=[4,2];
locks=[];
for i in range(len(seconds)) :
lock=thread.allocate_lock();
lock.acquire();
locks.append(lock);
print "main Thread begins:",ctime();
for i,lock in enumerate(locks):
thread.start_new_thread(loop,(i,choice(seconds),lock));
for lock in locks :
while lock.locked() :
pass;
print "main Thread ends:",ctime();
if __name__=="__main__" :
main();
這里對Python線程運行時加入了鎖監(jiān)控機制,介紹下紅色字體標志的幾個方法(其實紅色字體中的lock實質是thread.lockType實例。
從以上介紹可以看出這個Lock類非常類似于JDK5.0中的java.util.concurrent.locks.Lock。不知道Doug Lea有沒有參與這個模塊的開發(fā),只是比JAVA中的LOCK類多了一個方法locked,用于檢測Lock對象是否還處于加鎖的狀態(tài)。
所以上一個例子的工作原理就是在啟動線程的時候,給每個線程都加了一把鎖,直到線程運行介紹,再釋放這個鎖。同時在Python的main線程中用一個while循環(huán)來不停的判斷每個線程鎖已釋放。這個方法雖然避免了最開始的例子中人為的時間控制,但是還不方便,高效。
所以在較新的Python版本中,都推薦使用threading模塊。
看下threading模塊的API,有過JAVA開發(fā)經(jīng)驗的會發(fā)現(xiàn)它和java.lang.Thread類非常接近。這里需要說的一點就是threading的run方法可以返回函數(shù)值,這點在用于跟蹤和判斷線程運行正常與否非常有作用。
threading模塊支持三種方法來創(chuàng)建線程。而前兩種方式都與其Thread類有關??聪滤暮喴f明:
class Thread(_Verbose) : __init__(self, group=None, target=None, name=None, args=(), kwargs=None, verbose=None)
其中target指的是一個具體的函數(shù),或者可調用的類實例(這里指實現(xiàn)了__call__方法的類實例)
第一種方法:指定線程運行的時候調用的函數(shù)。舉例如下:
from time import ctime,sleep
import threading;
from random import choice
def loop(number,sec):
print "Thread ",number," begins and will sleep ",sec," at ",ctime();
sleep(sec);
print "Thread ",number,"ends at ",ctime();
def main():
seconds=[2,4];
threads=[];
array=range(len(seconds));
for i in array :
t=threading.Thread(target=loop,args=(i,choice(seconds)));
threads.append(t);
print "main Thread begins at ",ctime();
for t in threads :
t.start();
for t in threads :
t.join();
print "main Thread ends at ",ctime();
if __name__=="__main__" :
main();
這里target指向了一個具體的函數(shù)對象,而args傳入了該方法調用時所必須的參數(shù)。這里傳入了一個隨即的睡眠時間。其中thread.join表示要等待該線程終止,和java中的Thread.join(long millionseconds)作用一樣,如果不指定具體的時間的話,將會一直等待下去。
第二種方法就是指定一個可調用的類實例,實際上與前面一種非常的接近。如下所示:
from time import ctime,sleep
import threading;
from random import choice
class ThreadFunc(object):
def __init__(self,func,args,name):
self.func=func;
self.args=args;
self.name=name;
def __call__(self):
self.func(*self.args);
def loop(number,sec):
print "Thread ",number," begins and will sleep ",sec," at ",ctime();
sleep(sec);
print "Thread ",number,"ends at ",ctime();
def main():
seconds=[2,4];
threads=[];
array=range(len(seconds));
for i in array :
t=threading.Thread(target=ThreadFunc(loop,(i,choice(seconds)),loop.__name__));
threads.append(t);
print "main Thread begins at ",ctime();
for t in threads :
t.start();
for t in threads :
t.join();
print "main Thread ends at ",ctime();
if __name__=="__main__" :
main();
這里只是將target指向從一個函數(shù)對象變成了一個可調用的類實例。
重點推薦下第三種方式,用繼承threading.Thread的方式來實現(xiàn)線程,有過Java多線程應用的朋友一定會對下面的例子非常熟悉。
from time import ctime,sleep
import threading;
from random import choice
class MyThread(threading.Thread):
def __init__(self,func,args,name):
super(MyThread,self).__init__();
self.func=func;
self.args=args;
self.name=name;
def run(self):
self.result=self.func(*self.args);
def getResult(self):
return self.result;
def loop(number,sec):
print "Thread ",number," begins and will sleep ",sec," at ",ctime();
sleep(sec);
print "Thread ",number,"ends at ",ctime();
def main():
seconds=[2,4];
threads=[];
array=range(len(seconds));
for i in array :
t=MyThread(loop,(i,choice(seconds)),loop.__name__);
threads.append(t);
print "main Thread begins at ",ctime();
for t in threads :
t.start();
for t in threads :
t.join();
print "main Thread ends at ",ctime();
if __name__=="__main__" :
main();
從上面可以看出MyThread繼承了threading.Thread類,并在初始化方法中執(zhí)行了必要的參數(shù)賦值。值得注意的是在Java類的繼承中,如果不顯示的指定調用父類的構造方法,那么默認將調用父類的無參構造方法。而在Python中,就不會主動去調用。所以這里需要顯示的調用父類的初始化方法。
希望本文所述對大家的Python程序設計有所幫助。
相關文章
Windows下的Python 3.6.1的下載與安裝圖文詳解(適合32位和64位)
這篇文章主要介紹了Windows下的Python 3.6.1的下載與安裝圖文詳解(適合32位和64位),需要的朋友可以參考下2018-02-02
python 實現(xiàn)將txt文件多行合并為一行并將中間的空格去掉方法
今天小編就為大家分享一篇python 實現(xiàn)將txt文件多行合并為一行并將中間的空格去掉方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12
利用Python爬蟲爬取金融期貨數(shù)據(jù)的案例分析
從技術角度來看,經(jīng)過一步步解析,任務是簡單的,入門requests爬蟲及入門pandas數(shù)據(jù)分析就可以完成,本文重點給大家介紹Python爬蟲爬取金融期貨數(shù)據(jù)的案例分析,感興趣的朋友一起看看吧2022-06-06
python實現(xiàn)去除下載電影和電視劇文件名中的多余字符的方法
這篇文章主要介紹了python實現(xiàn)去除下載電影和電視劇文件名中的多余字符的方法,可以批量修改視頻文件名稱,非常具有實用價值,需要的朋友可以參考下2014-09-09
Django 忘記管理員或忘記管理員密碼 重設登錄密碼的方法
今天小編就為大家分享一篇Django 忘記管理員或忘記管理員密碼 重設登錄密碼的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05

