多线程中的 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

原文地址:https://www.cnblogs.com/dahuag/p/9198618.html

时间: 2025-01-14 06:00:27

多线程中的 Queue队列中join()与task_done() ,的相关文章

获取synchronized锁中的阻塞队列中的线程是非公平的

synchronized中阻塞队列的线程是非公平的 测试demo: import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.TimeUnit; public class SleepState { public static ThreadLocal<SimpleDateFormat> threadLocal = new

112 python程序中的进程操作-进程之间进行通信(mulitiProcessing Queue队列)

一.进程间通信 IPC(Inter-Process Communication) IPC机制:实现进程之间通讯 管道:pipe 基于共享的内存空间 队列:pipe+锁的概念--->queue 二.队列(Queue) 2.1 概念-----multiProcess.Queue 创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递. Queue([maxsize])创建共享的进程队列. 参数 :maxsize是队列中允许的最大项数.如果省略此参数,则无大小限制

Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍

1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过start方法启动线程--->线程变为可运行可执行状态,然后通过数据产生共享,线程产生互斥---->线程状态变为阻塞状态---->阻塞状态想打开的话可以调用notify方法. 这里Java5中提供了封装好的类,可以直接调用然后构造阻塞状态,以保证数据的原子性. 2.如何实现? 主要是实现Blo

iOS开发 多线程(一)GCD中dispatch队列知识

GCD编程的核心就是dispatch队列,dispatch block的执行最终都会放进某个队列中去进行,它类似NSOperationQueue但更复杂也更强大,并且可以嵌套使用.所以说,结合block实现的GCD,把函数闭包(Closure)的特性发挥得淋漓尽致. dispatch队列的生成可以有这几种方式: 1. dispatch_queue_t queue = dispatch_queue_create("com.dispatch.serial", DISPATCH_QUEUE_

pyhton中的Queue(队列)

什么是队列? 队列就像是水管子,先进先出,与之相对应的是栈,后进先出. 队列是线程安全的,队列自身有机制可以实现:在同一时刻只有一个线程在对队列进行操作. 存数据,取数据 1 import Queue 2 3 q = Queue.Queue() #调用队列生成对象 4 q.put(1) #存放第一个值到队列 5 q.put(2) #存放第二个值到队列 6 7 8 print 'get frist one:',q.get() #获取队列的第一个值 9 print 'get second on:',

java中使用FIFO队列:java.util.Queue实现多台服务器发邮件的代码

代码下载地址:http://www.zuidaima.com/share/1838230785625088.htm 原文:java中使用FIFO队列:java.util.Queue实现多台服务器发邮件的代码 最近由于zuidaima.com注册用户的增多,qq企业邮箱发送邮件会被封禁账号导致注册后面的用户收不到周总结,所以紧急开发了一套多账号,多服务器发送邮件的程序. 大概的设计思路如下: 1.服务器可以无限扩展,但由于qq企业邮箱是限定域名,所以要想多服务器还得有多域名,多账号也不行. 2.最

jQuery动画高级用法(上)——详解animation中的.queue()动画队列插队函数

决定对animate方面做一些总结,希望能给大家一些启发和帮助 从一个实际应用谈起 今天不谈animate().fadeIn().fadeOut().slideUp().show().hide()诸如此类的具体动画函 数,而谈谈几个并不常用的,甚至说是有点风马牛不相及,但又十分十分重要的动画函数queue(),dequeue(),和stop(). 先让我们从一个简单的例子谈,假设有一个购物功能,在结账之前,用户仍然可以把购物车里的删除至备选栏中(也许因为用户的资金不足,可以存储至下次购买) 好,

多线程编程学习六(Java 中的阻塞队列).

介绍 阻塞队列(BlockingQueue)是指当队列满时,队列会阻塞插入元素的线程,直到队列不满:当队列空时,队列会阻塞获得元素的线程,直到队列变非空.阻塞队列就是生产者用来存放元素.消费者用来获取元素的容器. 当线程 插入/获取 动作由于队列 满/空 阻塞后,队列也提供了一些机制去处理,或抛出异常,或返回特殊值,或者线程一直等待... 方法/处理方式 抛出异常 返回特殊值 一直阻塞 超时退出 插入方法 add(e) offer(e) put(e) offer(e, timeout, unit

python threading模块使用 以及python多线程操作的实践(使用Queue队列模块)

今天花了近乎一天的时间研究python关于多线程的问题,查看了大量源码 自己也实践了一个生产消费者模型,所以把一天的收获总结一下. 由于GIL(Global Interpreter Lock)锁的关系,纯的python代码处理一般逻辑的确无法活动性能上的极大提升,但是在处理需要等待外部资源返回或多用户的应用程序中,多线程仍然可以作为一个比较好的工具来进行使用. python提供了两个模块thread和threading 来支持python的多线程操作.通俗的讲一般现在我们只使用threading