假设我有以下代码:
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
我的程序会永久挂起,并且当队列中没有项目时也不会退出。
答案 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"