记一次 python多线程+Queue的坑逼之旅

时间:2021-08-03 17:38:32

背景~

在爬虫中,需要用到代理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个线程判断跳出,,然后就都出来了(线程全部结束)

print(threading.active_count()) 打印一下线程数量,,只剩下主线程,
 
over~