多線程中的 Queue隊列中join()與task_done() ,


Queue.task_done() 在完成一項工作之后,Queue.task_done()函數向任務已經完成的隊列發送一個信號
Queue.join() 實際上意味着等到隊列為空,再執行別的操作
如果線程里每從隊列里取一次,但沒有執行task_done(),則join無法判斷隊列到底有沒有結束,在最后執行個join()是等不到結果的,會一直掛起。
可以理解為,每task_done一次 就從隊列里刪掉一個元素,這樣在最后join的時候根據隊列長度是否為零來判斷隊列是否結束,從而執行主線程。
下面看個自己寫的例子:
下面這個例子,會在join()的地方無限掛起,因為join在等隊列清空,但是由於沒有task_done,它認為隊列還沒有清空,還在一直等。
class BdSpider(threading.Thread):
    """搜狗移動相關詞獲取爬蟲"""
    def __init__(self, waiting):
        super(BdSpider, self).__init__()
        self.waiting = waiting
        self.headers = {
                'User-Agent': "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Mobile Safari/537.36"
            }

    def run(self):
        flag = True
        while flag:
            ipone = self.waiting.get()
            error = self.get_html(ipone)
            if error == -1:
                flag = False
            # self.waiting.task_done()

    def get_html(self, ipone,num_retries=3):
        global allipus
        global error_counter
        error_counter = 0
        try:
            ip = {"http":"http://"+str(ipone) , "https":"http://"+str(ipone)}
            requests.get('https://m.sogou.com/', proxies=ip , timeout = 3 , headers = self.headers)
        except:
            error_counter += 1
            if num_retries > 0:
                return self.get_html(ipone , num_retries - 1)
        else:
            if str(ipone) not in str(allipus):
                print("保留ip:" + str(ipone))
                allipus.append(ipone)
            error_counter = 0
        if error_counter > 50:
            return -1

#更新獲取ip
def ipAction(ipsss):
    ipall = []
    if ipsss:
        for iss in ipsss:
            if iss:
                ipall.append(iss)
    url = "http://api.ip.data5u.com/api/get.shtml?order=194469bc039df0eb7580e09541aa0624&num=20&carrier=0&protocol=2&an1=1&an2=2&an3=3&sp1=1&sp2=2&sp3=3&sort=1&system=1&distinct=0&rettype=1&seprator=%0A"
    for num in range(5):
        time.sleep(10)
        sss = requests.get(url)
        soup = BeautifulSoup(sss.text ,'html.parser')
        guoneiip = str(soup).split("\n")
        for ip in guoneiip:
            if ip:
                ipall.append(ip)
    wait_list = Queue()
    thread_num = 20        
    for keyip in ipall:
        if keyip:
            keyip = keyip.strip()#去除空格
            wait_list.put(keyip)#往Queue添加
    for i in range(thread_num):
        thread = BdSpider(wait_list)
        thread.setDaemon(True)#設置守護進程
        thread.start()
    wait_list.join()
    return allipus
allipus = []

 

傳入一個

Queue   waiting當
self.waiting.task_done()此行注釋程序會一直卡死,無限掛起狀態。此時被認為線程沒結束,被 .join()。守護。主線程結束不了

原文參考http://www.vuln.cn/8610


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM