Python Queue使用者

时间:2015-08-05 08:57:23

标签: python thread-safety

我是python的新手,并开始学习一些高级概念。这里我使用python队列来消费和生成线程。这是一个线程安全吗?在这里,我将列表项添加到队列并在使用者线程中检索它。有没有最好的方法呢?

from queue import Queue
import threading
import time

class producer(threading.Thread):

    def __init__(self, list_of_numbers):
        threading.Thread.__init__(self)
        self.list_items = list_of_numbers

    def run(self):
        for i in self.list_items:
            queue.put(str(i))

class consumer(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while queue.not_empty:
            queue_ret = queue.get()
            print("Retrieved", queue_ret)


queue = Queue()
producers = producer([10,20,5,4,3,2,1])
consumers = consumer()

producers.start()
consumers.start()
producers.join()
consumers.join()

3 个答案:

答案 0 :(得分:1)

Docs明确声明Queue是线程安全的:

  

Queue模块实现多生产者,多消费者队列。它   当信息必须时,在线程编程中特别有用   在多个线程之间安全地交换。

https://docs.python.org/2/library/queue.html

答案 1 :(得分:1)

首先使用队列初始化您的消费者类。

然后在消费者线程类的末尾添加queue.task_done()。这将告诉线程在将来的queue.get()调用中忽略该队列项。最终这意味着你的队列将“空”并且线程将完成他们的工作。

class consumer(threading.Thread):

  def __init__(self, queue):
      threading.Thread.__init__(self)
      self.queue = queue

  def run(self):
      while queue.not_empty:
          queue_ret = self.queue.get()
          print("Retrieved", queue_ret)
          self.queue.task_done()

# to start your threads, for example 5 threads
for i in range(5):
    consumers = consumer(queue)
    consumers.start()

答案 2 :(得分:0)

要完成消费者线程,您可以将sentinel值推送到队列中,如下所示:

from queue import Queue
import threading
import time

class producer(threading.Thread):

    def __init__(self, list_of_numbers):
        threading.Thread.__init__(self)
        self.list_items = list_of_numbers

    def run(self):
        for i in self.list_items:
            queue.put(str(i))
        print("Producer Finished")

class consumer(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        done = False
        while not done:
            queue_ret = queue.get()
            if queue_ret is None:
                done = True
            else:
                print("Retrieved", queue_ret)
            queue.task_done()
        print("Consumer Finished")


queue = Queue()
producers = [producer([10,20,5,4,3,2,1])]
consumers = [consumer()]

for producer in producers:
    producer.start()

for consumer in consumers:
    consumer.start()

for producer in producers:
    producer.join()

for consumer in consumers:
    queue.put(None)

for consumer in consumers:
    consumer.join()

print("Finished")