作者回复: task_done()是配合join()使用的,join() 会让队列一直处于阻塞状态,直到queue里面所有的message都被get()取出来调用了task_done()才能返回,不用这个函数会让join()出现无限挂起的问题,不符合我们写程序的预期。 它和join()一起使用来判断队列里是否还有message需要处理的一种机制,如果看它的代码实现,会发现它通过信号与join()进行配合的。 或许在初学阶段,大家更容易理解这种用法 while not workQueue.empty(): pass 就是一直循环,直到队列为空。 两种机制都可以判断为队列是否为空,看你需要那种方法和想要在哪种场景下使用。
作者回复: 问题出在产生了一个数据,但是并没有将他放在队列里面(queue.put(num))啊,当第二个线程执行到num = queue.get()时会“暂停”,直到有数据写入队列,所以你只看到打印生产数据,没看到消费数据
作者回复: 一定要判断的,我这里没有演示是因为queue包对已满队列有自己的处理机制,而不是抛出异常。可以自己尝试一下,如果只往队列写,不读取会发生什么结果?通过官方文档查看如何判断队列是否已满?
作者回复: 在文件内,模块(函数)外声明的都是全局变量, 这里使用的global是声明在类中使用的queue是全局变量,避免class内部误声明同名的queue变量发生冲突。
作者回复: 是否您的文件名就是 queue.py 呢?
作者回复: 是的,这是引用了queue库时引入的,类似异常处理。
作者回复: 这里的queue用的python库,它是线程安全的,里面实现了锁机制
作者回复: python多线程和linux的线程原理相同,参考操作系统的线程原理即可
作者回复: task_done()作用:如果 join() 当前正在阻塞,在所有条目都被处理后,将解除阻塞 参考等待排队的任务被完成的示例: import queue import threading def worker(): while True: item = q.get() if item is None: break print(item, 'run') #注释q.task_done()这行查看程序运行结果进行对比 q.task_done() q = queue.Queue() threads = [] num_worker_threads = 2 for i in range(num_worker_threads): t = threading.Thread(target=worker) t.start() threads.append(t) for item in range(10): 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()
作者回复: p1是ProducerThread()类的实例化,ProducerThread()继承了threading类,当我调用p1.start()方法时,class ProducerThread(Thread)类会自动调用run()方法。 首先强调一下这段代码的目的性:这里我写ProducerThread(name='p1')目的是想使用 p1 c1 c2的名字替代 thread-1 、 thread-2、 thread-3 ...这样的默认名称,为的是输出时方便大家看效果。这个功能要在实例化的时候使用,所以不能用__init__ 初始化name python传参是可以传“关键字参数”的,这里使用的name='p1'并不是第一个参数是线程名,而是我在run()方法定义了name变量,实例化的时候重传name进行覆盖。