【发布时间】:2014-12-19 07:41:09
【问题描述】:
如何在 Python 中从多个线程中使用 Queue.get()?
我想做:一个线程用Queue.put(xxx)发送一个数据,有些线程得到同样的数据。 这个想法就像“信号”。我想在没有 PyQt 的情况下做到这一点。
例如:
#!/usr/bin/python
import threading
import Queue
queue= Queue.Queue()
def Func1():
while True:
data= queue.get()
print 'Func1:got',data
if data=='q': break
def Func2():
while True:
data= queue.get()
print 'Func2:got',data
if data=='q': break
def MainThread():
while True:
data= raw_input('q to quit > ')
queue.put(data)
if data=='q': break
t1= threading.Thread(name='func1', target=Func1)
t2= threading.Thread(name='func2', target=Func2)
tm= threading.Thread(name='main', target=MainThread)
t1.start()
t2.start()
tm.start()
t1.join()
t2.join()
tm.join()
这里我希望 Func1 和 Func2 从 MainThread 中获取相同的数据,但 Func1 和 Func2 中只有一个可以获取数据。
如果你有一个好主意,请告诉我。
非常感谢!
编辑于 2014-12-19 12:51 EST
基于 Reut Sharabani 的想法,我实现了一个信号类。
#!/usr/bin/python
import threading
import Queue
class TSignal:
def __init__(self):
self.queues= {} #Map from index to queue
self.counter= 0
self.locker= threading.Lock()
def NewQueue(self):
with self.locker:
idx= self.counter
self.counter+= 1
self.queues[idx]= Queue.Queue()
queue= self.TQueue(self,idx,self.queues[idx])
return queue
def DeleteQueue(self,idx):
with self.locker:
del self.queues[idx]
def put(self,item,block=True,timeout=None):
for idx,queue in self.queues.iteritems():
queue.put(item,block,timeout)
class TQueue:
def __init__(self,parent,idx,queue):
self.parent= parent
self.idx= idx
self.queue= queue
def __enter__(self):
return self
def __exit__(self,e_type,e_value,e_traceback):
self.parent.DeleteQueue(self.idx)
def get(self,block=True,timeout=None):
return self.queue.get(block,timeout)
signal= TSignal()
def Func1():
with signal.NewQueue() as queue:
while True:
data= queue.get()
print '\nFunc1:got[%r]\n'%data
if data=='q': break
def Func2():
with signal.NewQueue() as queue:
while True:
data= queue.get()
print '\nFunc2:got[%r]\n'%data
if data=='q': break
def MainThread():
while True:
data= raw_input('q to quit > ')
signal.put(data)
if data=='q': break
t1= threading.Thread(name='func1', target=Func1)
t2= threading.Thread(name='func2', target=Func2)
tm= threading.Thread(name='main', target=MainThread)
t1.start()
t2.start()
tm.start()
t1.join()
t2.join()
tm.join()
TSignal 的使用非常简单。在 getter 函数中,插入一条 with 语句,如:
with signal.NewQueue() as queue:
然后以与Queue.get()相同的方式使用队列:
data= queue.get()
在 putter 函数中,只需像 Queue.put() 一样使用 put:
signal.put(data)
问题是如果线程数为N,TSignal需要维护N个队列,而TSignal.put实际上调用了Queue.put N次。所以还是想知道有没有更好的办法。
您对此有什么意见吗?
【问题讨论】:
-
只是为了清楚。您希望两个线程都获得相同的数据吗?所以当我给“somestring”作为输入时,输出应该是“'Func1:got somestring”和“'Func2:got somestring”?
-
是的,完全正确。我希望两个(或更多)线程都能获得由单个发送者发送的相同数据。
-
添加了另一个解决方案,我认为更好。
-
Hey Reut,这是一个很好的解决方法,我想知道是否有任何方法可以利用这里的异步来加快调度到队列的速度?可能是一个不错的改进!代码也可以使用 Python 3.6+ 的更新
标签: python multithreading queue signals