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

标签 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,我的程序将永远挂起,并且当队列中没有项目时不会退出。

最佳答案

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

if queue.empty(): break

...导致竞争条件。

假设队列中只剩下一项,并且两个线程几乎同时评估上述条件。对于两个线程,该条件的计算结果均为False...因此它们不会中断。 较快的线程获取最后一个项目,而较慢的线程则永远卡在语句 item = queue.get() 中。

考虑到守护进程模式为False这一事实,程序将等待所有线程完成。这永远不会发生。

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

下面这句话可能会让你感到困惑:

The entire Python program exits when no alive non-daemon threads are left.

...但请考虑:如果使用 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"

关于python - 了解 Python 队列并设置线程作为守护线程运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33035027/

相关文章:

Laravel 多个 worker 并且速率受限

laravel - 如何使用 laravel 队列邮件编写单元测试?

Python selenium 无法通过 id 找到元素

python - Web2Py 中的每次调用都会解释代码吗?

python - 属性错误: object has no attribute 'listbox' ?

c++ - 嵌入式 Boost::Python 和 C++:并行运行

python - 在 python 源/脚本中查找依赖项

java - Apache Kafka : 3 partitions, 消费者组中有3个消费者,每个消费者应该是多线程的

java - GWT:多线程

带队列的Python线程: how to avoid to use join?