selenium+python之python多線程


程序、進程及線程的區別

計算機程序是磁盤中可執行的二進制數據(或者其他類型)他們只有在被讀取到內存中,被操作系統調用才開始他們的生命周期。

進程是程序的一次執行,每個進程都有自己的地址空間,內存,數據棧,以及其他記錄其運行軌跡的輔助數據,操作系統管理再其上面運行的所有進程,並為這些進程公平得分配時間。

線程與進程相似,不同的是所有的線程都運行在同一個進程中,共享相同的運行環境。

 

1.單線程

單線程時,當處理器需要處理多個任務時,必須對這些任務安排執行的順序,並按照這個順序來執行任務。

 1 from time import sleep, ctime
 2 
 3 
 4 # 聽音樂
 5 def music():
 6     print('i was listening to music! %s' % ctime())
 7     sleep(2)
 8 
 9 
10 # 看電影
11 def movie():
12     print('i was at the movies! %s' % ctime())
13     sleep(5)
14 
15 
16 if __name__ == '__main__':
17     music()
18     movie()
19     print('all end:', ctime())

增加循環功能:

 1 from time import sleep, ctime
 2 
 3 
 4 # 聽音樂
 5 def music(func, loop):
 6     for i in range(loop):
 7         print('i was listening to music! %s !%s' % (func, ctime()))
 8         sleep(2)
 9 
10 
11 # 看電影
12 def movie(func, loop):
13     for i in range(loop):
14         print('i was listening to music! %s !%s' % (func, ctime()))
15         sleep(5)
16 
17 
18 if __name__ == '__main__':
19     music('愛情買賣', 2)
20     movie('一代宗師', 2)
21     print('all end:', ctime())

給music()和movie()兩個函數設置參數:播放文件和播放次數。函數中通過for循環控制播放的次數。

2、多線程

python通過兩個標准庫thread和threading提供對線程的支持。thread提供了低級別的,原始的線程以及一個簡單的鎖。threading基於Java的線程模型設計。鎖(lock)和條件變量(condition)在Java中時對象的基本行為(每個對象都自帶了鎖和條件變量),而在python中則是獨立的對象。

(1)threading模塊

避免使用thread模塊,原因是它不支持守護線程。當主線程退出時,所有的子線程不關他們是否還在工作,都會被強行退出。但是我們並不希望發生這種行為。就要引入守護線程的概念。threading支持守護線程。

 1 from time import sleep, ctime
 2 import threading
 3 
 4 
 5 # 聽音樂
 6 def music(func, loop):
 7     for i in range(loop):
 8         print('i was listening to music! %s !%s' % (func, ctime()))
 9         sleep(2)
10 
11 
12 # 看電影
13 def movie(func, loop):
14     for i in range(loop):
15         print('i was listening to music! %s !%s' % (func, ctime()))
16         sleep(5)
17 
18 
19 # 創建線程數組
20 threads = []
21 # 創建線程t1,並添加到線程數組
22 t1 = threading.Thread(target=music, args=('愛情買賣', 2))
23 threads.append(t1)
24 # 創建線程t2,並添加到線程數組
25 t2 = threading.Thread(target=music, args=('一代宗師', 2))
26 threads.append(t2)
27 
28 if __name__ == '__main__':
29     # 啟動線程
30     for t in threads:
31         t.start()
32     # 守護線程
33     for t in threads:
34         t.join()
35 
36     print('all end:', ctime())

注:import threading: 引入線程模塊

       threads = []:創建線程數組,用於裝載線程。

       threading.Thread(): 通過調用threading模塊的Thread()方法來創建線程。

運行結果如下:

從上面運行的結果可以看出,兩個子線程(music,movie)同時啟動於10分15秒,知道所有線程結束於10分17秒共好使2秒。從執行的結果可以看出兩個線程達到了並行工作。

優化線程的創建

從上面例子中發現線程的創建很麻煩,每創建一個線程都需要一個t(t1,t2.。。。。)當創建的線程較多時,這樣的操作及其的不方便。

 1 from time import sleep, ctime
 2 import threading
 3 
 4 
 5 # 創建超級播放器
 6 def super_player(file_, loop):
 7     for i in range(2):
 8         print('start playing: %s !%s' % (file_, ctime()))
 9         sleep(2)
10 # 播放文件與播放時長
11 lists = {'愛情買賣.mp3':3,'阿凡達.mp4':5,'傳奇.mp3':4}
12 
13 threads = []
14 files = range(len(lists))
15 print(files)
16 # 創建線程
17 print(lists.items())
18 for file_,time in lists.items():
19     t = threading.Thread(target=super_player,args=(file_,time))
20     print(t)
21     threads.append(t)
22 
23 if __name__ == '__main__':
24     # 啟動線程
25     for t in files:
26         threads[t].start()
27     # 守護線程
28     for t in files:
29         threads[t].join()
30 
31     print(' end:%s'% ctime())

 

 1 from time import sleep, ctime
 2 import threading
 3 
 4 
 5 # 創建超級播放器
 6 def super_player(file_, loop):
 7     for i in range(3):  # 控制線程的循環次數
 8         print('start playing: %s !%s' % (file_, ctime()))
 9         sleep(3)  # 每次循環的間接次數
10 
11 
12 # 播放文件與播放時長
13 lists = {'愛情買賣.mp3': 3, '阿凡達.mp4': 5, '傳奇.mp3': 4}
14 
15 threads = []
16 files = range(len(lists))
17 print(len(lists))
18 
19 print(files)  # 打印的結果是range(0,3)
20 # 創建線程
21 print(lists.items())
22 for file_, time in lists.items():
23     t = threading.Thread(target=super_player, args=(file_, time))
24     print(t)
25     threads.append(t)
26 
27 if __name__ == '__main__':
28     # 啟動線程
29     for t in files:
30         threads[t].start()
31     # 守護線程
32     for t in files:
33         threads[t].join()
34 
35     print(' end:%s' % ctime())

 創建了一個super_player()函數,這個函數可以接收播放文件和播放時長,可以播放任何文件。

創建了一個lists字典用於存放播放文件名與時長,通過for循環讀取字典,並調用super_play()函數創建字典,接着將創建的字典都追加到threads數組中。

最后通過循環啟動線程數組threads中的線程。

 

創建線程類(未懂)

 1 import threading
 2 from time import sleep, ctime
 3 
 4 
 5 # 創建線程類
 6 class MyThread (threading.Thread):
 7     def __init__(self, func, args, name=''):
 8         threading.Thread.__init__ (self)
 9         self.func = func
10         self.args = args
11         self.name = name
12 
13     def run(self):
14         self.func (*self.args)
15 
16 
17 # 創建超級播放器
18 def super_player(file_, loop):
19     for i in range (3):  # 控制線程的循環次數
20         print ('start playing: %s !%s' % (file_, ctime ()))
21         sleep (3)  # 每次循環的間接次數
22 
23 
24 # 播放文件與播放時長
25 lists = {'愛情買賣.mp3': 3, '阿凡達.mp4': 5, '傳奇.mp3': 4}
26 
27 threads = []
28 files = range (len (lists))
29 print (len (lists))
30 
31 print (files)  # 打印的結果是range(0,3)
32 # 創建線程
33 print (lists.items ())
34 for file_, time in lists.items ():
35     t = threading.Thread (target=super_player, args=(file_, time))
36     print (t)
37     threads.append (t)
38 
39 if __name__ == '__main__':
40     # 啟動線程
41     for t in files:
42         threads[t].start ()
43     # 守護線程
44     for t in files:
45         threads[t].join ()
46 
47     print (' end:%s' % ctime ())

MyThread(threading.Thread)

創建MyThread類,用於繼承threading.Thread類

__init__()類的初始化方法對func,args,name等參數進行初始化。

self.func (*self.args)函數的作用是當函數參數已經存在於一個元組或者字典中時,apply()間接地調用函數。args是一個包含將要提供給函數的按位置傳遞的參數元組。
如果省略了args,則任何參數不會被傳遞,kwargs是一個包含關鍵字參數的字典。



注:以上內容為轉載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM