了解Python队列并将线程设置为作为守护程序线程运行

时间:2015-10-09 09:46:13

标签: python multithreading queue

假设我有以下代码:

import Queue
import threading
import time

def basic_worker(queue, thread_name):
    while True:
       if queue.empty(): break

       print "Starting %s" % (threading.currentThread().getName()) + "\n"
       item = queue.get()
       ##do_work on item which might take 10-15 minutes to complete
       queue.task_done()

       print "Ending %s" % (threading.currentThread().getName()) + "\n"


def basic(queue):
# http://docs.python.org/library/queue.html

    for i in range(10):
       t = threading.Thread(target=basic_worker,args=(queue,tName,))
       t.daemon = True
       t.start()
    queue.join()       # block until all tasks are done
    print 'got here' + '\n'

queue = Queue.Queue()

for item in range(4):
     queue.put(item)



basic(queue)


print "End of program"

我的问题是,如果我设置t.daemon = True它是否会退出代码,从而杀死需要10-15分钟才能从队列中item做一些工作的线程?因为根据我的阅读,它说如果有任何守护线程存活,程序将退出。我的理解是,花费很长时间处理项目的线程也将不完全退出。如果我没有设置t.daemon = True我的程序会永久挂起,并且当队列中没有项目时也不会退出。

1 个答案:

答案 0 :(得分:1)

如果t.daemon = False,程序永远挂起的原因是以下代码块......

if queue.empty(): break

......导致竞争条件。

想象一下,队列中只剩下一个项目,两个线程几乎同时评估上面的条件。对于两个线程,条件评估为False ...因此他们不会break。 较快的线程获取最后一个项目,而较慢的线程永远挂起在语句item = queue.get()中。

尊重守护进程模式为False的事实,程序等待所有线程完成。这从未发生过。

从我的角度来看,您提供的代码(使用t.daemon = True)工作正常。

可能以下句子让你感到困惑:

  

当没有剩下活着的非守护程序线程时,整个Python程序退出。

...但考虑一下:如果使用t.daemon = True从主线程启动所有线程,则唯一的非守护程序线程是主线程本身。所以当主线程完成时程序就存在了。 ......由于queue.join()语句,直到队列为空才会发生这种情况。因此,您在子线程内部长时间运行的计算不会被中断。

使用守护程序线程和queue.join()时,无需检查queue.empty()。

这应该足够了:

#!/bin/python
import Queue
import threading
import time

def basic_worker(queue, thread_name):
    print "Starting %s" % (threading.currentThread().getName()) + "\n"
    while True:
       item = queue.get()
       ##do_work on item which might take 10-15 minutes to complete
       time.sleep(5) # to simulate work
       queue.task_done()

def basic(queue):
# http://docs.python.org/library/queue.html

    for i in range(10):
       print 'enqueuing', i
       t = threading.Thread(target=basic_worker, args=(queue, i))
       t.daemon = True
       t.start()
    queue.join()       # block until all tasks are done
    print 'got here' + '\n'

queue = Queue.Queue()

for item in range(4):
     queue.put(item)

basic(queue)


print "End of program"