【问题标题】:Thread from another class in a Producer Consumer with Queue带有队列的生产者消费者中另一个类的线程
【发布时间】:2016-11-20 19:10:21
【问题描述】:

我想为消费者生产者实现一个。我还没有实现消费者,因为我对生产者有问题。目的是在互联网上下载一些文件。线程在自定义对象的方法中启动。线程是 threading.Thread 的子类对象。这是代码

downloader_thread.py

from threading import Thread

import time


class Downloader(Thread):
    def __init__(self, queue, out_queue):
        super(Downloader, self).__init__()
        self.queue = queue
        self.out_queue = out_queue

    def run(self):
        while True:
            page = self.queue.get()
            if page:
                print "Simulating download"
                print "Downloading page ", page
                time.sleep(3)
                self.out_queue.put(page)

            self.queue.task_done()

main_class.py

from Queue import Queue

from downloader_thread import Downloader


class Main(object):
    def __init__(self):
        self.queue = Queue(0)
        self.out_queue = Queue(0)
        self.threads = []
        self.max_threads = 5

    def download(self):
        page = 1
        for i in range(self.max_threads):
            download_thread = Downloader(self.queue, self.out_queue)
            download_thread.setDaemon(True)
            download_thread.start()
            self.threads.append(download_thread)

        while page < 100:
            self.queue.put(page)
            page += 1

        self.queue.join()

        for thread in self.threads:
            thread.join()


if __name__ == "__main__":

    main = Main()
    main.download()
    while not main.out_queue.empty():
        print main.out_queue.get()

问题是线程正常启动所有五个,它们执行 run 方法中的内容,但不要停止,所以 while 永远不会被执行。我对线程和并发编程有点陌生,所以请温柔:)

关键是要有一个消费者线程来处理代码的while部分,而不是在“ma​​in”中处理这个while:部分代码

【问题讨论】:

    标签: python multithreading queue producer-consumer


    【解决方案1】:

    您的线程永远不会终止,因为它们有一个带有无限循环的run() 方法。在你的download() 方法中你join() 到那些线程:

            for thread in self.threads:
                thread.join()
    

    因此程序被阻止。只需删除连接,因为您似乎打算让这些线程在程序的生命周期内持续存在。

    【讨论】:

    • 感谢您的快速回复。终止线程的工作由队列负责,queue.join() 和 queue.task_done() 正确吗?
    • 不,在您当前的实现中,线程在程序的生命周期内永远不会终止。它们确实允许终止 python 程序,因为它们是守护线程。当queue 用完时,它们会被阻止在page = self.queue.get() 中。 queue.task_done() 确实是正确的,您可以使用 queue.join(),即等待队列中的所有项目被获取和处理。
    • 当下载返回当前实现时,有没有办法结束线程?估计不对吧?有没有办法让他们停下来?我听说强制停止线程不是最佳做法?
    • 如果你真的需要他们停下来,让他们在某些条件下循环而不是while True:,例如。这也要求您不要无限期地阻止get()。添加超时并捕获并忽略Queue.Empty
    • 好的...总结一下...当可调用对象退出(运行或目标)时,线程被破坏。添加有关如何终止线程的逻辑是开发人员的责任。非常感谢。
    猜你喜欢
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 2020-11-09
    • 2015-09-25
    • 2018-07-13
    • 1970-01-01
    • 2023-03-06
    • 2013-09-30
    相关资源
    最近更新 更多