1. 程式人生 > >Python多線程實例

Python多線程實例

none and 作用 內存 ted seq http 影響 python

前言

  感覺理解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一下

遇到的坑

  感覺理解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多線程實例