Python解释器挂起 - 试验线程和队列

时间:2015-01-07 13:32:25

标签: python-2.7 python-multithreading

成功挂起后退出

import threading
import Queue as queue 
import time
import sys

class WorkItem(threading.Thread):

    def __init__(self):
        self.P1 = 20
        self.P2 = 40

        threading.Thread.__init__(self)

    def run(self):
        print "P1 = %d" % (self.P1)
        print "P2 = %d" % (self.P2)

class WorkQueue(object):
    def __init__(self,queueLimit = 5):

        self.WorkQueue = queue.Queue(queueLimit)
        self.dispatcherThread = threading.Thread(target=self.DequeueWorker)
        self.dispatcherThread.start()
        self.QueueStopEvent = threading.Event()
        self.QueueStopEvent.clear()

    def DequeueWorker(self):
        print "DequeueWorker Enter .."
        while not self.QueueStopEvent.isSet():
            workItem = self.WorkQueue.get(True)
            workItem.start()

    def DispatchToQueue(self,workItem):

        self.WorkQueue.put(workItem,True)

    def Stop(self):
        self.QueueStopEvent.set()
        self.queue = None 


def main():
    q = WorkQueue()
    for i in range(1,20):
        t  = WorkItem()
        q.DispatchToQueue(t)

    time.sleep(10)
    q.Stop()



if __name__ == "__main__":
  main()

我可以看到DequeueWorker是一个仍在运行和待定的人,并试图理解为什么因为我确实发出Stop事件的信号。我期待循环会退出。

>>> $w
=> Frame id=0, function=DequeueWorker
   Frame id=1, function=run
   Frame id=2, function=__bootstrap_inner
   Frame id=3, function=__bootstrap

帮助赞赏!!

1 个答案:

答案 0 :(得分:1)

您在get设置为block时调用True,这意味着它将阻塞,直到某个项目在队列中实际可用。在您的代码中,一旦工作队列耗尽,下一个get将无限期地阻塞,因为它正在等待永远不会发生的额外工作项(并且不会让while循环的下一次迭代执行,因此QueueStopEvent的状态不再被检查。尝试将DequeueWorker方法修改为:

def DequeueWorker(self):
    print "DequeueWorker Enter .."
    while not self.QueueStopEvent.isSet():
        try:
          workItem = self.WorkQueue.get(True, timeout=3)
          workItem.start()
        except queue.Empty: continue

现在,当工作队列耗尽后调用get时,它将超时(在这种情况下3秒后,我随意选择)并引发queue.Empty异常。在这种情况下,我们只是让循环继续到下一次迭代,当QueueStopEvent最终被设置时,循环将自行中断。

其他选项是在get设置为block的情况下调用False,或在get_nowait / try内使用except方法块:

workItem = self.WorkQueue.get(False)
workItem = self.WorkQueue.get_nowait()

虽然当队列为空时会产生非常紧张的while循环。