Selenium 2自動化測試實戰41(多線程技術)

多線程技術python

python經過兩個標準庫thread和threading提供對線程的支持。thread提供了低級別的,原始的線程以及一個簡單的鎖。threading基於Java的線程模型設計。數組

1.threading模塊
應該避免使用thread模塊,緣由是它不支持守護線程。當主線程退出時,全部的子線程無論他們是否還在工做,都會被強行退出。有時候並不但願出現此種行爲,所以就引入了守護線程的概念。threading模塊支持守護線程,因此,咱們直接使用threading來改進上述的例子。多線程

#threads.py
#coding:utf-8 from time import sleep,ctime import threading #聽音樂任務 def music(func,loop): for i in range(loop): print('i was listening to %s! %s' % (func,ctime())) sleep(2) #看電影任務 def movies(func,loop): for i in range(loop): print('i was watch the %s!%s' %(func,ctime())) sleep(5) #建立線程數組 threads=[] #建立線程t1,並添加到線程數組 t1=threading.Thread(target=music,args=(u'愛情買賣',2)) threads.append(t1) #建立線程t2,並添加到線程數組 t2=threading.Thread(target=movies,args=(u'阿凡達',2)) threads.append(t2) if __name__=="__main__": #啓動線程 for t in threads: t.start() #守護線程 for t in threads: t.join() print ('all end %s' %ctime())

執行以後,結果以下圖所示:app

-import threading:引入線程模塊
-threads=[]:建立線程數組,用於裝載線程。
-threading.Thread():經過調用threading模塊的Thread()方法來建立線程。函數

經過for循環遍歷threads數組中所裝載的線程,start()開始線程活動,join()等待線程終止。若是不使用join()方法對每一個線程作等待終止,那麼在線程運行的過程當中可能會去執行最後的打印「all end…」
代碼分析:
從上面的運行結果能夠看出,兩個子線程(music/movie)同時啓動於46分09秒,直到全部線程結束於46分19秒,總耗時10秒,movie的兩次電影循環共須要10秒,music的歌曲循環須要4秒,從執行結果看出兩個線程達到了並行工做。oop

 

2.優化線程的建立
上述例子中,每建立一個線程都須要建立一個t(t1,t2,……),當建立的線程較多時,這樣不方便,所以下面例子將做出改進。優化

#player.py
#coding:utf-8 from time import sleep,ctime import threading #建立超級播放器 def super_player(file_,time): for i in range(2): print 'Start playing:%s! %s' %(file_,ctime()) sleep(time) #播放的文件與播放時長 lists={u'愛情買賣.mp3':3,u'阿凡達.mp4':5,u'我和你.mp3':4} threads=[] files=range(len(lists)) #建立線程 for file_,time in lists.items(): t=threading.Thread(target=super_player,args=(file_,time)) threads.append(t) if __name__=="__main__": #啓動線程 for t in files: threads[t].start() for t in files: threads[t].join() print 'all end"%s' %ctime()

執行以後,結果以下圖所示:spa

 

 

此例中,對播放器的功能也作了加強,首先,建立了一個super_player()函數,這個函數能夠接收播放文件和播放時長,能夠播聽任何文件。線程

而後,咱們建立了一個lists字典用於存放播放文件名與時長,經過for循環讀取字典,並調用super_player()函數建立字典,接着將建立的字典都追加到threads數組中。設計

 

3.建立線程類
除直接使用python所提供的線程類外,還能夠根據需求自定義本身的線程類。

#mythread.py
#coding:utf-8 from time import sleep,ctime import threading #建立線程類 class MyThreads(threading.Thread): def __init__(self,func,args,name=''): threading.Thread.__init__(self) self.func=func self.args=args self.name=name def run(self): self.func(*self.args) def super_play(file_,time): for i in range(2): print('Start playing:%s! %s' %(file_,ctime())) sleep(time) lists={u'愛情買賣.mp3':3,u'阿凡達.mp4':5,u'我和你.mp3':4} threads=[] files=range(len(lists)) for file_,time in lists.items(): t=MyThreads(super_play,(file_,time),super_play.__name__) threads.append(t) if __name__=='__main__': #啓動線程 for i in files: threads[i].start() for i in files: threads[i].join() print'all end:%s' %ctime()

執行以後,結果以下圖所示:

 

 

MyThreads(threading.Thread)
建立MyThread類,用於繼承threading.Thread類
__init__()類的初始化方法對func、args、name等參數進行初始化。


在python2中,apply(func[,args[,kwargs]])函數的做用是當函數參數已經存在於一個元組或字典中,apply()間接地調用函數。args是一個包含將要提供給函數的按位置傳遞的參數的元組。若是省略了args,則任何參數都不會被傳遞,kwargs是一個包含關鍵字參數的字典。

Python3中已經再也不支持apply()函數,因此將
-apply(self.func,self.args)
修改成
Self.func(*self.args)

最後,線程的建立與啓動與前面的例子相同,惟一的區別是建立線程使用的是MyThreads類,線程的入參形式也有所改變。

相關文章
相關標籤/搜索