我希望在执行多线程编程时,在Python中拥有一个单一的生产者,多个消费者体系结构。我希望有这样的操作:
所以我需要所有消费者从制作人那里获得相同的数据。
当我使用Queue执行此操作时,我意识到除了第一个消费者之外的所有消费者都会因为我的实施而受到匮乏。
一种可能的解决方案是为每个消费者线程建立一个唯一的队列,其中生产者在多个队列中推送相同的数据。有更好的方法吗?
from threading import Thread
import time
import random
from Queue import Queue
my_queue = Queue(0)
def Producer():
global my_queue
my_list = []
for each in range (50):
my_list.append(each)
my_queue.put(my_list)
def Consumer1():
print "Consumer1"
global my_queue
print my_queue.get()
my_queue.task_done()
def Consumer2():
print "Consumer2"
global my_queue
print my_queue.get()
my_queue.task_done()
P = Thread(name = "Producer", target = Producer)
C1 = Thread(name = "Consumer1", target = Consumer1)
C2 = Thread(name = "Consumer2", target = Consumer2)
P.start()
C1.start()
C2.start()
在上面的例子中,当C1消耗P1产生的数据时,C2无限期地被阻塞。我想要的是C1和C2都能够访问由P1产生的SAME数据。
感谢任何代码/指针!
答案 0 :(得分:2)
您的制作人只创建一项工作:
my_queue.put(my_list)
例如,将my_list放两次,两位消费者都可以工作:
def Producer():
global my_queue
my_list = []
for each in range (50):
my_list.append(each)
my_queue.put(my_list)
my_queue.put(my_list)
因此,通过这种方式,您可以将两个作业放入具有相同列表的队列中。
但是我必须警告你:在没有线程同步的情况下修改不同线程中的相同数据通常是个坏主意。
无论如何,使用一个队列的方法对你来说不起作用,因为一个队列应该用具有相同算法的线程处理。
所以,我建议你为每个消费者提供独特的队列,因为其他解决方案并不是那么简单。
答案 1 :(得分:1)
那么每个线程的队列呢?
作为启动每个消费者的一部分,您还将创建另一个队列,并将其添加到"所有线程队列"的列表中。然后启动生产者,将所有队列的列表传递给他,然后他可以将数据推送到所有队列中。
答案 2 :(得分:1)
一个单一生产者和五个消费者的例子,经过验证。
from multiprocessing import Process, JoinableQueue
import time
import os
q = JoinableQueue()
def producer():
for item in range(30):
time.sleep(2)
q.put(item)
pid = os.getpid()
print(f'producer {pid} done')
def worker():
while True:
item = q.get()
pid = os.getpid()
print(f'pid {pid} Working on {item}')
print(f'pid {pid} Finished {item}')
q.task_done()
for i in range(5):
p = Process(target=worker, daemon=True).start()
producers = []
# it is easy to extend it to multi producers.
for i in range(1):
p = Process(target=producer)
producers.append(p)
p.start()
# make sure producers done
for p in producers:
p.join()
# block until all workers are done
q.join()
print('All work completed')
说明: