背景~
在爬蟲中,需要用到代理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 = False
def 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個線程判斷跳出,,然后就都出來了(線程全部結束)