記一次 python多執行緒+Queue的坑逼之旅
背景~
在爬蟲中,需要用到代理ip,本人寫了一個模組來獲取和過濾代理ip(用多執行緒過濾,),,,在主執行緒中判斷可用的代理ip少於一定值了,獲取新的可用ip,問題來了。。多次呼叫代理ip模組之後報錯:
can't start new thread !!!!!!!!!!!!!!!?????????????????????????
what the fuck!!!!神馬鬼,一次只開20個執行緒怎麼會建立不了新的執行緒,,在檢查之後發現開啟的執行緒功能完成之後雖然結束了,但是還佔用著資源,,(沒釋放,在死迴圈??),持續開啟新的執行緒使我的電腦到達所能開啟的最大執行緒了!!!!!!
於是寫了一個例子來測試一下結果,程式碼如下:
import threading , time from queue import Queue class BdSpider(threading.Thread): def __init__(self, waiting): super(BdSpider, self).__init__() self.waiting = waitingdef run(self): flag = True while flag: ipone = self.waiting.get() self.waiting.task_done() if self.waiting.empty(): print("ppppppppppppppppppppppppppppp") flag = Falsedef ipAction(): for i in range(10): aaa = [] wait_list = Queue() thread_num = 20 for keyip in range(2000): if keyip: wait_list.put(keyip)#往Queue新增 for ii in range(100): print(ii + i*100) thread = BdSpider(wait_list) thread.setDaemon(True)#設定守護程序 thread.start() aaa.append(thread) wait_list.join() print("-------------------------------") print(threading.active_count())#列印當前執行緒數 ipAction() print("main ------") print(threading.active_count())
列印當前的執行緒數量確實是在持續增加,,一直到極限,,,,
剛開始一直在找怎麼把執行緒強制殺死,,,怎麼釋放執行緒佔得資源,,,,,在網上找了兩天(日樂購),,測試各種各樣的可能,,no!!!!!!!!!!!!
程式碼中重寫類中run方法判斷佇列為空只走了一次!!!!!!!!!!!!!!!!
??????????why
心中無數個草擬嗎奔騰而過~~
於是乎查詢與Queue有關的東西,功夫不負有心人,終於在python的官網找到了答案,官網原話和例子:
Queue.
join
()
阻止直到佇列中的所有專案都被獲取並處理。
每當專案新增到佇列時,未完成任務的計數就會增加。每當消費者執行緒呼叫task_done()
以指示該專案已被檢索並且其上的所有工作都已完成時,計數就會下降。當未完成任務的數量降至零時,join()
取消阻止。如何等待排隊任務完成的示例:
def worker(): while True: item = q.get() if item is None: break do_work(item) q.task_done() q = queue.Queue() threads = [] for i in range(num_worker_threads): t = threading.Thread(target=worker) t.start() threads.append(t) for item in source(): q.put(item) # block until all tasks are done q.join() # stop workers for i in range(num_worker_threads): q.put(None) for t in threads: t.join()
,,,,照著更改之後,解決問題,,列印執行緒數量為1(主執行緒),,,,
有一個疑問?:為什麼開啟的100個執行緒只有1個判斷為空,子執行緒結束,剩餘的99個執行緒為什麼不判斷,不跳出!!!!!!(有大佬懂得請不吝賜教)
總結:
以我的理解,100個執行緒中只有一個執行緒判斷為空,出來了,join結束,不知道剩餘的99個執行緒沒判斷為空,,不知道死在裡邊哪裡了。官網例子是在佇列重新put進100個None,給100個執行緒判斷跳出,,然後就都出來了(執行緒全部結束)
print(threading.active_count()) 列印一下執行緒數量,,只剩下主執行緒, over~