gpt4 book ai didi

python - 正确关闭守护线程

转载 作者:太空宇宙 更新时间:2023-11-04 00:26:14 27 4
gpt4 key购买 nike

我创建了自己的线程类,将在线程池中使用,如下所示:

class SendFilesThread(threading.Thread):
execute = True

def __init__(self, port, rate, fileQueue):
self.daemon = True
self.fileQueue = fileQueue
#Other initialization

def run(self):
while SendFilesThread.execute == True or not self.fileQueue.empty():
self.filename = self.fileQueue.get()
#some file processing
self.fileQueue.task_done()

@staticmethod
def terminate():
SendFilesThread.execute = False

在程序的主线程中,处理完所有文件后,我尝试按如下方式关闭线程池:

SendFilesThread.terminate()
for t in threadPool:
if t.is_alive():
t.join()
exit()

我的理解是,如果我调用 join(),它将阻止调用线程(在本例中为主线程)继续执行,直到加入的线程完成处理。我的问题是,尽管线程完成了,但它永远不会返回到主线程,程序只是挂起。关闭线程池时我做错了什么吗?

最佳答案

有两件事。首先,从设计的角度来看,将 execute 标志置于类级别有点奇怪。通常最好将它作为每个类实例的标志。

其次,您有竞争条件。 execute 标志被多个线程访问,并且不受同步原语(如互斥锁)的保护。这意味着 terminate() 调用可以在任何工作线程检查标志之后运行(并设置标志),但在该线程之前尝试使下一个文件名出队。因为您在没有超时的情况下调用 get(),工作线程将卡在这里,而主线程将阻塞在 t.join() 调用中。死锁随之而来。

有很多方法可以解决这个问题。您可以使用线程同步原语(例如互斥锁)来保护 execute 标志,或者使用 threading.Event 对象代替简单的 bool 值。

另一个在我看来更简单的解决方案是在同一个队列上发送一个“sentinel”值,它指示线程应该退出。看起来您正在发送字符串文件名,因此空字符串可能是一个不错的选择。 (None 也很常用。)

每个线程的工作循环现在看起来像这样:

def run(self):
while True:
self.filename = self.fileQueue.get()
if self.filename == '':
return
# Process file

不是 terminate() 静态方法,主线程为您拥有的每个工作线程放置一个空字符串(即 fileQueue.enqueue('')) .

关于python - 正确关闭守护线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47337625/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com