我是否应该总是使用 threading.Thread.join()?

1 投票
1 回答
1669 浏览
提问于 2025-04-18 16:29

我从这里学到了多线程的知识,并且我把最后一个例子当作我所有多线程应用的模板。下面是代码:

#!/usr/bin/python

import Queue
import threading
import time

exitFlag = 0

class myThread (threading.Thread):
    def __init__(self, threadID, name, q):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.q = q
    def run(self):
        print "Starting " + self.name
        process_data(self.name, self.q)
        print "Exiting " + self.name

def process_data(threadName, q):
    while not exitFlag:
        queueLock.acquire()
        if not workQueue.empty():
            data = q.get()
            queueLock.release()
            print "%s processing %s" % (threadName, data)
        else:
            queueLock.release()
        time.sleep(1)

threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = Queue.Queue(10)
threads = []
threadID = 1

# Create new threads
for tName in threadList:
    thread = myThread(threadID, tName, workQueue)
    thread.start()
    threads.append(thread)
    threadID += 1

# Fill the queue
queueLock.acquire()
for word in nameList:
    workQueue.put(word)
queueLock.release()

# Wait for queue to empty
while not workQueue.empty():
    pass

# Notify threads it's time to exit
exitFlag = 1

#here is where i do my write to file, the last operation**

# Wait for all threads to complete
for t in threads:
    t.join()
#print "Exiting Main Thread"

正如你所看到的,这个例子在所有线程上使用了t.join(),这样可以等待它们完成。我的实际版本非常长,而且是一个大项目,但这不是重点。我只是想知道有没有什么特殊情况是可以不使用join()的?

1 个回答

9

我只是想知道有没有什么特殊情况是可以不使用 join() 的?

显而易见的情况是,当有其他线程(你要连接的那个线程)正在连接这个线程时,你就不需要再做了,不过这个你应该早就知道了。:)

首先,daemon 线程是可以不需要连接的(通常也不应该连接)。你可以直接放弃它们,它们会在你的主线程退出时突然被终止。(当然,确保在守护线程中不要做一些危险的事情,比如覆盖文件。)

其次,如果你不去 join 你的(正常的、非守护的)线程,实际上并没有明确记录会发生什么。你的主线程可能会以某种随机的顺序等待所有线程,或者它可能会在后台线程继续工作的同时退出并返回到命令行,或者它可能会杀掉这些线程。但如果你根本不在乎会发生哪种情况,那就可以不 join

第三,在很多平台上,发生的事情是有明确规定的(通常是“它们都会以某种随机的顺序被 join”)。比如说,如果你正在写一个只需要在 Red Hat Linux 下的 CPython 上运行的程序,并且你确定在 Red Hat Linux 下 CPython 的行为,那么如果你的程序结构让你很难跟踪线程,直接不 join 也是合理的(可以加个注释说明一下),而不是重新设计整个程序。

最后,虚拟线程(dummy threads)是不用连接的。但如果你有虚拟线程却不知道自己有虚拟线程,那你就有比 join 更大的问题了。

撰写回答