记一次 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 = 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个线程判断跳出,,然后就都出来了(线程全部结束)