Thread.join()在python中到底做什么?这是Thread.join()的错误用法吗?

时间:2018-06-26 18:45:11

标签: python multithreading python-multithreading

我最近开始学习如何用python编写多线程程序,对于初学者来说,我开始尝试不用使用队列。

在下面的代码中,loadFunction只是线程的示例目标函数。 假定,要等到wait(list)参数中提供的所有线程执行完毕(并且我正在尝试使用join()来实现)。然后之后开始打印出指定的数字范围。 这是期望的行为。

在主程序中,我创建了两个线程,它们不等待任何其他线程开始计数。然后,我创建了第三个线程,该线程应该等待前两个线程执行完毕才开始计数。

但是这没有发生。在测试中,我发现三个线程开始同时执行,而第三个线程没有像我预期的那样等待前两个线程完成执行。

所以我的问题是,我对Thread.join()函数缺少什么知识,我可以对代码进行哪些更改以实现所需的结果?

代码:

""" Note: Python 3.3 onwards required since daemon was added as an initializable
    property from python 3.3 onwards."""

import threading

def loadFunction(name, start, end, wait=[]):
    """ wait should be a list of threads to wait for """
    map(lambda th: th.join(), wait)
    for number in range(start, end):
        print("%s : %d" % (name, number))

if __name__ == "__main__":
    t1 = threading.Thread(target=loadFunction, args=("Thread1", 1, 101), name="Thread1" ,daemon=True)
    t2 = threading.Thread(target=loadFunction, args=("Thread2", 101, 201), name="Thread2", daemon=True)
    t3 = threading.Thread(target=loadFunction, args=("Thread3", 1000, 1101, [t1, t2]), name="Thread3", daemon=True)

    t1.start()
    t2.start()
    t3.start()

    # wait for all of the daemon processes to finish before we close the program
    t1.join()
    t2.join()
    t3.join()

    print("done!")

部分结果(一次运行):

Thread1 : 1
Thread1 : 2
Thread1 : 3
Thread1 : 4
Thread1 : 5
Thread1 : 6
Thread2 : 101
Thread2 : 102
Thread2 : 103
Thread2 : 104
Thread2 : 105
Thread2 : 106
Thread2 : 107
Thread2 : 108
Thread2 : 109
Thread1 : 7
Thread1 : 8
Thread1 : 9
Thread1 : 10
Thread1 : 11
Thread3 : 1000
Thread1 : 12
Thread1 : 13
Thread3 : 1001
Thread1 : 14
Thread3 : 1002
Thread1 : 15
Thread3 : 1003
Thread1 : 16
Thread2 : 110

这是我编写此代码时想到的两件事(引自the official documentation):

  

join(timeout = None)

     

等待直到线程终止。这阻止了通话   直到调用join()方法的线程终止为止

在我的示例代码中,“调用线程”是调用loadFunction函数的哪个线程?我有一个 轻微 怀疑,事实并非如此,进程本身调用了函数而不是线程,因此该线程不是等待中的那个,而是进程等待。如果是这种情况,我该如何解决?我感觉会涉及到队列... 如果,这首先是原因。

和:

  

一个线程可以被多次join()。

是导致我两次对同一线程使用join的原因。

P.S。我是第一次在python中学习线程,但这是在学习C语言中的派生过程之后,因此,也许我 可能 在这里变得有些困惑。如果两者不相关,那么我很抱歉,我的印象是两者相似(尽管显然不相同,因为一个人拆分了流程,而另一个则在流程内部创建了线程)。

谢谢。

2 个答案:

答案 0 :(得分:1)

  

无论调用loadFunction函数的那个​​线程是“调用线程”吗?

调用线程是称为join的线程。因此t1.join()t2.join()t3.join()导致主线程被阻塞,并且loadFunction内部的联接会导致t3被阻塞,如果map的计算不是很懒惰的话

  

我该如何解决?

您在loadFunction内部的联接未执行,因为map在迭代之前不会执行任何代码。正如MaxNoe所建议的那样,您应该改用普通的for循环。

def loadFunction(name, start, end, wait=[]):
    """ wait should be a list of threads to wait for """
    for t in wait:
        t.join()
    for number in range(start, end):
        print("%s : %d" % (name, number))

答案 1 :(得分:0)

如果要在开始第三个线程之前等待两个第一个线程完成,请不要在start()插入其他两个线程之前在第三个线程上调用join()

t1.start()
t2.start()

# wait for the threads above to finish before starting the third
t1.join()
t2.join()

t3.start() #now start it
t3.join()  # wait for it to finish