Python多線程實例
前言
感覺理解python多線程用“切換”和“共享”就差不多了。這裏就貼上一個搶車票的小小實例,還有自己在編程過程中遇到的坑.....
實例:搶車票
搶車票有三類人:會員、弄了加速包、普通人。
說說區別:
錢帶來的不公平:會員先跑,然後加速包,最後普通人
可以欣慰的公平:跑道一樣長
守護線程SetDaemon
不設置守護進程
1 import threading 2 import time 3 #使用函數式 4 5 #會員 6 def vip(t1): 7 globalexam1num 8 time.sleep(2) #等待時間相同,區別是進場的先後順尋 9 if num == 15: 10 print("用時:", time.time() - t1) 11 exit(0) 12 num += 1 13 print(‘會員,當前被搶票數:‘, num) 14 #有加速包的家夥 15 def aboostOne(t1): 16 global num 17 time.sleep(2) #等待時間相同,區別是進場的先後順尋 18 if num == 15:19 print("用時:",time.time()-t1) 20 exit(0) 21 num+=1 22 print(‘加速包,當前被搶票數:‘, num) 23 24 #沒有加速包的苦逼 25 def commonOne(t1): 26 global num 27 time.sleep(2) #等待時間相同,區別是進場的先後順尋 28 if num == 15: 29 print("用時:", time.time() - t1) 30 exit(0) 31 num += 1 32print(‘苦逼青年,當前被搶票數:‘, num) 33 34 if __name__ ==‘__main__‘: 35 t1 =time.time() #開始時間 36 num =0 #只有15張票 37 #vip優先,來3個 38 for i in range(3): 39 threading.Thread(target=vip,args=(t1,)).start() 40 #加速包其次,來7個 41 for i in range(7): 42 threading.Thread(target=aboostOne,args=(t1,)).start() 43 #苦逼青年最後,來10個 44 for i in range(10): 45 threading.Thread(target=commonOne,args=(t1,)).start()
結論:
1.加速包可以搶的比會員卡 === 多線程不一定按順序進行
2.最終打出了5個用時 === 一個線程exit()之後,其他線程不受影響,繼續運行
再看看設置守護
其他代碼不變,只給苦逼青年daemon.圖中有兩種方式
結果:
苦逼青年搶票被中斷,拋出異常 === 設置守護意味著不重要,主線程退出,守護進程隨即被中斷
join()設置阻塞
在setDaemon的情況下join,只測試苦逼青年的
結果:
完美運行完了 === join的作用:被join的子線程執行完之後,主線程才能進行。
這裏就算SetDaemon,主線程也帶等苦逼青年運行完。SetDaemon後,用join,相當於沒有設置守護進程
作用:當你想做完一些事,再做另一些事,就可以join一下
遇到的坑
感覺理解python多線程用“切換”和“共享”就差不多了。這裏就貼上一個搶車票的小小實例,還有自己在編程過程中遇到的坑.....
實例:搶車票
搶車票有三類人:會員、弄了加速包、普通人。
說說區別:
錢帶來的不公平:會員先跑,然後加速包,最後普通人
可以欣慰的公平:跑道一樣長
守護線程SetDaemon
不設置守護進程
1 import threading 2 import time 3 #使用函數式 4 5 #會員 6 def vip(t1): 7 global num 8 time.sleep(2) #等待時間相同,區別是進場的先後順尋 9 if num == 15: 10 print("用時:", time.time() - t1) 11 exit(0) 12 num += 1 13 print(‘會員,當前被搶票數:‘, num) 14 #有加速包的家夥 15 def aboostOne(t1): 16 global num 17 time.sleep(2) #等待時間相同,區別是進場的先後順尋 18 if num == 15: 19 print("用時:",time.time()-t1) 20 exit(0) 21 num+=1 22 print(‘加速包,當前被搶票數:‘, num) 23 24 #沒有加速包的苦逼 25 def commonOne(t1): 26 global num 27 time.sleep(2) #等待時間相同,區別是進場的先後順尋 28 if num == 15: 29 print("用時:", time.time() - t1) 30 exit(0) 31 num += 1 32 print(‘苦逼青年,當前被搶票數:‘, num) 33 34 if __name__ ==‘__main__‘: 35 t1 =time.time() #開始時間 36 num =0 #只有15張票 37 #vip優先,來3個 38 for i in range(3): 39 threading.Thread(target=vip,args=(t1,)).start() 40 #加速包其次,來7個 41 for i in range(7): 42 threading.Thread(target=aboostOne,args=(t1,)).start() 43 #苦逼青年最後,來10個 44 for i in range(10): 45 threading.Thread(target=commonOne,args=(t1,)).start()exam1
結論:
1.加速包可以搶的比會員卡 === 多線程不一定按順序進行
2.最終打出了5個用時 === 一個線程exit()之後,其他線程不受影響,繼續運行
再看看設置守護
其他代碼不變,只給苦逼青年daemon.圖中有兩種方式
結果:
苦逼青年搶票被中斷,拋出異常 === 設置守護意味著不重要,主線程退出,守護進程隨即被中斷
join()設置阻塞
在setDaemon的情況下join,只測試苦逼青年的
結果:
完美運行完了 === join的作用:被join的子線程執行完之後,主線程才能進行。
這裏就算SetDaemon,主線程也帶等苦逼青年運行完。SetDaemon後,用join,相當於沒有設置守護進程
作用:當你想做完一些事,再做另一些事,就可以join一下
遇到的坑
pymysql.err.InternalError: Packet sequence number wrong - got 45 expected 0
原因:
使用了多線程,多線程共享了同一個數據庫連接,但每個execute前沒有加上互斥鎖
方法:
方法一:每個execute前加上互斥鎖
lock.acquire()
cursor.execute(command,data)
lock.release()
方法二:
每個線程擁有自己的數據庫連接,即在線程調用函數中加上數據庫連接代碼
方法三:
所有線程共用一個連接池,需要考慮線程總數和連接池連接數上限的問題
另外
threading.Thread(target =,args=(,))
args應當傳入Tuble(元組)
第二:傳入的參數不是引用傳遞,而是新分配了內存。估計是把參數初始化到類的成員裏面去了吧
轉自:https://www.cnblogs.com/heiao10duan/p/9373237.html
Python多線程實例