所以,我有一个基本的例子,我写的是我使用多个线程和一个Queue独立调用不同的函数并执行某些任务。这种逻辑是正确的还是有任何改进的范围? 我没有使用像http://www.ibm.com/developerworks/aix/library/au-threadingpython/中所示的线程的单独类,因为这将不必要地使我试图实现的工作流程变得复杂,其中每个线程调用一个单独的函数并将其放在同一个队列中,以后我可以使用它分析结果。
from Queue import Queue
from threading import Thread
class Scheduler():
def __init__(self):
self.id=10
def add(self,q,id):
self.id+=id
q.put('added %d' % self.id)
q.task_done()
def mul(self,q,id):
self.id*=id
q.put('multiplied : %d' % self.id)
q.task_done()
if __name__=='__main__':
id=5
sch1=Scheduler()
sch2=Scheduler()
q= Queue()
t1=Thread(target=sch1.add, args=(q,id,))
t1.start()
t2=Thread(target=sch2.mul, args=(q,id,))
t2.start()
print q.get()
print q.get()
q.join()
答案 0 :(得分:1)
这里有几个问题:
首先,通过self.id
和+=
递增*=
不是原子的,因此如果要同时运行多个add
和/或mul
方法相同的Scheduler
对象,self.id
可能因为两个或多个实例互相踩踏而导致错误计算。您可以通过使用threading.Lock
保护增量操作来解决此问题。
其次,您滥用Queue.task_done
/ Queue.join
方法。 task_done
和join
背后的想法是将生产者线程put
项目放到Queue
上,然后在将所有工作项添加到Queue
之后},调用queue.join()
等待一个或多个消费者处理所有工作项。消费者调用queue.get()
,处理工作项,然后调用queue.task_done()
以表示已完成处理该项目。你有点倒退 - 你从同一个线程中调用queue.put
和queue.task_done
。您使用Queue
的方式,使用此模式确实没有意义 - 您只需使用Queue
将结果传回主线程。你也可以这样做:
from Queue import Queue
from threading import Thread
class Scheduler():
def __init__(self):
self.id=10
def add(self,q,id):
self.id+=id
q.put('added %d' % self.id)
def mul(self,q,id):
self.id*=id
q.put('multiplied : %d' % self.id)
if __name__=='__main__':
sch1 = Scheduler()
sch2 = Scheduler()
q = Queue()
t1 = Thread(target=sch1.add, args=(q,id,))
t1.start()
t2 = Thread(target=sch2.mul, args=(q,id,))
t2.start()
print q.get()
print q.get()