了解如何使用多个线程在python中使用Queue调用不同的函数?

时间:2015-03-31 17:57:32

标签: python multithreading

所以,我有一个基本的例子,我写的是我使用多个线程和一个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()

1 个答案:

答案 0 :(得分:1)

这里有几个问题:

首先,通过self.id+=递增*=不是原子的,因此如果要同时运行多个add和/或mul方法相同的Scheduler对象,self.id可能因为两个或多个实例互相踩踏而导致错误计算。您可以通过使用threading.Lock保护增量操作来解决此问题。

其次,您滥用Queue.task_done / Queue.join方法。 task_donejoin背后的想法是将生产者线程put项目放到Queue上,然后在将所有工作项添加到Queue之后},调用queue.join()等待一个或多个消费者处理所有工作项。消费者调用queue.get(),处理工作项,然后调用queue.task_done()以表示已完成处理该项目。你有点倒退 - 你从同一个线程中调用queue.putqueue.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()