国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

【跟我一起學Python吧】Python多線程

2019-11-14 17:37:01
字體:
來源:轉載
供稿:網友

 其實自我感覺Python的多線程很類似于java的多線程機制,但是比JAVA的多線程更靈活。在早期的Python多線程實現中,采用了thread模塊。例如:   

   

Python代碼  收藏代碼
  1. from time import ctime,sleep  
  2. from thread import start_new_thread  
  3. def loop1():  
  4.     PRint "enter loop1:",ctime();  
  5.     sleep(3);  
  6.     print "leave loop1:",ctime();  
  7.   
  8. def loop2():  
  9.     print "enter loop2:",ctime();  
  10.     sleep(5);  
  11.     print "leave loop2:",ctime();  
  12.   
  13. def main():  
  14.     print "main begin:",ctime();  
  15.     start_new_thread(loop1, ());  
  16.     start_new_thread(loop2,());  
  17.     sleep(8);  
  18.     print "main end:",ctime();  
  19.   
  20. if __name__=="__main__":  
  21.     main();  

 

 

 

    簡單介紹下這個代碼塊中的函數功能,sleep是線程睡眠時間,幾乎等價于JAVA中的Thread.sleep(millionseconds)

    start_new_thread是實例化一個線程并運行的方法,方法的第一個參數接受一個線程運行時所執行的函數對象,第二個參數是方法執行時所需要的參數,以一個元組的形式傳入。   

    這大概是最早期的Python多線程實現了,注意代碼中的main線程里的sleep(8)。這里的睡眠時間只能比3+5大,而不能小。如果小于這個時間,那么main主線程會提前退出,導致無論其子線程是否是后臺線程,都將會中斷,從而拋出線程中斷異常,類似于Java的ThreadInterruptException。這個致命的影響幾乎就是這個模塊后期被拋棄的罪魁禍首。

    當然在早期的Python多線程中,你可以利用加鎖的機制來避免出現這個情況。稍微改動下以上代碼:

    

Python代碼  收藏代碼
  1. import thread;  
  2. from time import sleep,ctime;  
  3. from random import choice  
  4. #The first param means the thread number  
  5. #The second param means how long it sleep  
  6. #The third param means the Lock  
  7. def loop(nloop,sec,lock):  
  8.     print "Thread ",nloop," start and will sleep ",sec;  
  9.     sleep(sec);  
  10.     print "Thread ",nloop," end  ",sec;  
  11.     lock.release();  
  12.   
  13. def main():  
  14.     seconds=[4,2];  
  15.     locks=[];  
  16.     for i in range(len(seconds)) :  
  17.         lock=thread.allocate_lock();  
  18.         lock.acquire();  
  19.         locks.append(lock);  
  20.           
  21.     print "main Thread begins:",ctime();  
  22.     for i,lock in enumerate(locks):  
  23.         thread.start_new_thread(loop,(i,choice(seconds),lock));  
  24.     for lock in locks :  
  25.         while lock.locked() :   
  26.             pass;  
  27.     print "main Thread ends:",ctime();  
  28.   
  29. if __name__=="__main__" :  
  30.     main();  

 

 

 

    這里對Python線程運行時加入了鎖監控機制,介紹下紅色字體標志的幾個方法(其實紅色字體中的lock實質是thread.lockType實例。 ):

    從以上介紹可以看出這個Lock類非常類似于JDK5.0中的java.util.concurrent.locks.Lock。不知道Doug Lea有沒有參與這個模塊的開發,哈哈~~(純屬YY),只是比JAVA中的LOCK類多了一個方法locked,用于檢測Lock對象是否還處于加鎖的狀態。

    所以上一個例子的工作原理就是在啟動線程的時候,給每個線程都加了一把鎖,直到線程運行介紹,再釋放這個鎖。同時在Python的main線程中用一個while循環來不停的判斷每個線程鎖已釋放。這個方法雖然避免了最開始的例子中人為的時間控制,但是還不方便,高效。

    所以在較新的Python版本中,都推薦使用threading模塊。

    看下threading模塊的API,有過JAVA開發經驗的會發現它和java.lang.Thread類非常接近。這里需要說的一點就是threading的run方法可以返回函數值,這點在用于跟蹤和判斷線程運行正常與否非常有作用。

   threading模塊支持三種方法來創建線程。而前兩種方式都與其Thread類有關。看下它的簡要說明:

 

    

Python代碼  收藏代碼
  1. class Thread(_Verbose) :  
  2.      __init__(self, group=None, target=None, name=None, args=(), kwargs=None, verbose=None)  

 

 

 

 

 

   其中target指的是一個具體的函數,或者可調用的類實例(這里指實現了__call__方法的類實例) 

  第一種方法:指定線程運行的時候調用的函數。舉例如下:

 

 

Python代碼  收藏代碼
  1. from time import ctime,sleep  
  2. import threading;  
  3. from random import choice  
  4.   
  5. def loop(number,sec):  
  6.     print "Thread ",number," begins and will sleep ",sec," at ",ctime();  
  7.     sleep(sec);  
  8.     print "Thread ",number,"ends at ",ctime();  
  9.       
  10. def main():  
  11.     seconds=[2,4];  
  12.     threads=[];  
  13.     array=range(len(seconds));  
  14.     for i in array :  
  15.         t=threading.Thread(target=loop,args=(i,choice(seconds)));  
  16.         threads.append(t);  
  17.     print "main Thread begins at ",ctime();  
  18.     for t in threads :  
  19.         t.start();  
  20.     for t in threads :  
  21.         t.join();          
  22.     print "main Thread ends at ",ctime();  
  23.   
  24. if __name__=="__main__" :  
  25.     main();  

 

 

 

    從圖上可以看出,這里target指向了一個具體的函數對象,而args傳入了該方法調用時所必須的參數。這里傳入了一個隨即的睡眠時間。其中thread.join表示要等待該線程終止,和java中的Thread.join(long millionseconds)作用一樣,如果不指定具體的時間的話,將會一直等待下去。

 

 

   

   第二種方法就是指定一個可調用的類實例,實際上與前面一種非常的接近。如下所示:

  

Python代碼  收藏代碼
  1. from time import ctime,sleep  
  2. import threading;  
  3. from random import choice  
  4.   
  5. class ThreadFunc(object):  
  6.     def __init__(self,func,args,name):  
  7.         self.func=func;  
  8.         self.args=args;  
  9.         self.name=name;  
  10.           
  11.     def __call__(self):  
  12.         self.func(*self.args);  
  13.   
  14. def loop(number,sec):  
  15.     print "Thread ",number," begins and will sleep ",sec," at ",ctime();  
  16.     sleep(sec);  
  17.     print "Thread ",number,"ends at ",ctime();  
  18.       
  19. def main():  
  20.     seconds=[2,4];  
  21.     threads=[];  
  22.     array=range(len(seconds));  
  23.     for i in array :  
  24.         t=threading.Thread(target=ThreadFunc(loop,(i,choice(seconds)),loop.__name__));  
  25.         threads.append(t);  
  26.     print "main Thread begins at ",ctime();  
  27.     for t in threads :  
  28.         t.start();  
  29.     for t in threads :  
  30.         t.join();          
  31.     print "main Thread ends at ",ctime();  
  32.   
  33. if __name__=="__main__" :  
  34.     main();  

 

 

 

   這里只是將target指向從一個函數對象變成了一個可調用的類實例。

 

    重點推薦下第三種方式,用繼承threading.Thread的方式來實現線程,有過Java多線程應用的朋友一定會對下面的例子非常熟悉。

   

Python代碼  收藏代碼
  1. from time import ctime,sleep  
  2. import threading;  
  3. from random import choice  
  4.   
  5. class MyThread(threading.Thread):  
  6.     def __init__(self,func,args,name):  
  7.         super(MyThread,self).__init__();  
  8.         self.func=func;  
  9.         self.args=args;  
  10.         self.name=name;  
  11.               
  12.     def run(self):  
  13.         self.result=self.func(*self.args);  
  14.   
  15.     def getResult(self):  
  16.         return self.result;  
  17.       
  18. def loop(number,sec):  
  19.     print "Thread ",number," begins and will sleep ",sec," at ",ctime();  
  20.     sleep(sec);  
  21.     print "Thread ",number,"ends at ",ctime();  
  22.       
  23. def main():  
  24.     seconds=[2,4];  
  25.     threads=[];  
  26.     array=range(len(seconds));  
  27.     for i in array :  
  28.         t=MyThread(loop,(i,choice(seconds)),loop.__name__);  
  29.         threads.append(t);  
  30.     print "main Thread begins at ",ctime();  
  31.     for t in threads :  
  32.         t.start();  
  33.     for t in threads :  
  34.         t.join();          
  35.     print "main Thread ends at ",ctime();  
  36.   
  37. if __name__=="__main__" :  
  38.     main();  

    

    從上面可以看出MyThread繼承了threading.Thread類,并在初始化方法中執行了必要的參數賦值。值得注意的是在Java類的繼承中,如果不顯示的指定調用父類的構造方法,那么默認將調用父類的無參構造方法。而在Python中,就不會主動去調用。所以這里需要顯示的調用父類的初始化方法。

推薦一個網站:程序人生


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 山阳县| 陆川县| 潞城市| 梨树县| 阿城市| 汝阳县| 池州市| 宁城县| 德惠市| 三穗县| 轮台县| 昆山市| 东乡县| 元阳县| 祁连县| 宜良县| 尤溪县| 晋州市| 友谊县| 星座| 灵寿县| 三穗县| 海原县| 出国| 巴彦淖尔市| 洛浦县| 铁力市| 扬中市| 雷山县| 金堂县| 深泽县| 敖汉旗| 曲松县| 金溪县| 屯留县| 蒙阴县| 泸水县| 芮城县| 五莲县| 乡城县| 繁峙县|