当我不显式调用 join 方法时,线程会发生什么情况?
What happens to threads when I dont explicitly call the join method?
我需要对我的程序中的数据进行一些网络调用。我打算并行调用它们,但并非所有都需要完成。
我现在拥有的是
thread1 = makeNetworkCallThread()
thread1.start()
thread2 = makeLongerNetworkCallThread()
thread2.start()
thread1.join()
foo = thread1.getData()
thread2.join()
if conditionOn(foo):
foo = thread2.getData()
# continue with code
问题在于,即使较短的网络调用成功,我也需要等待较长的网络调用完成所需的时间
如果我在 if 语句中移动 thread2.join() 会发生什么? join 方法可能永远不会被调用。这会导致陈旧的线程等出现一些问题吗?
thread2
仍将继续 运行(根据 GIL 的注意事项,但由于它是网络调用,因此可能不是问题)是否 join
是否被调用。不同之处在于主上下文是否在继续执行其他操作之前等待线程结束 - 如果您能够在没有完成更长的网络调用的情况下继续处理,那么应该没有问题。
请记住,在所有线程完成之前,程序不会真正结束(解释器不会退出)。根据此长网络调用对程序其余部分 运行 时间的延迟(如果您不等待),程序可能看起来已经结束,但实际上并没有退出,直到网络呼叫结束。考虑这个愚蠢的例子:
# Python 2.7
import threading
import time
import logging
def wasteTime(sec):
logging.info('Thread to waste %d seconds started' % sec)
time.sleep(sec)
logging.info('Thread to waste %d seconds ended' % sec)
if __name__ == '__main__':
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
t1 = threading.Thread(target=wasteTime, args=(2,))
t2 = threading.Thread(target=wasteTime, args=(10,))
t1.start()
t2.start()
t1.join()
logging.info('Main context done')
这是日志输出:
$ time python test.py
2015-01-15 09:32:12,239 Thread to waste 2 seconds started
2015-01-15 09:32:12,239 Thread to waste 10 seconds started
2015-01-15 09:32:14,240 Thread to waste 2 seconds ended
2015-01-15 09:32:14,241 Main context done
2015-01-15 09:32:22,240 Thread to waste 10 seconds ended
real 0m10.026s
user 0m0.015s
sys 0m0.010s
请注意,尽管主上下文在 2 秒后(thread1
完成所花费的时间)结束,但程序在 thread2
完成之前不会完全退出(执行开始后十秒)。在这种情况下(特别是如果输出被这样记录),我认为最好在某个时候显式调用 join
并在您的日志中明确标识这是程序正在做的事情,以便在 user/operator 看来它不像挂起的那样。对于我的愚蠢示例,这可能看起来像在主上下文的末尾添加这样的行:
logging.info('Waiting for thread 2 to complete')
t2.join()
这将生成不那么神秘的日志输出:
$ time python test.py
2015-01-15 09:39:18,979 Thread to waste 2 seconds started
2015-01-15 09:39:18,979 Thread to waste 10 seconds started
2015-01-15 09:39:20,980 Thread to waste 2 seconds ended
2015-01-15 09:39:20,980 Main context done
2015-01-15 09:39:20,980 Waiting for thread 2 to complete
2015-01-15 09:39:28,980 Thread to waste 10 seconds ended
real 0m10.027s
user 0m0.015s
sys 0m0.010s
我需要对我的程序中的数据进行一些网络调用。我打算并行调用它们,但并非所有都需要完成。
我现在拥有的是
thread1 = makeNetworkCallThread()
thread1.start()
thread2 = makeLongerNetworkCallThread()
thread2.start()
thread1.join()
foo = thread1.getData()
thread2.join()
if conditionOn(foo):
foo = thread2.getData()
# continue with code
问题在于,即使较短的网络调用成功,我也需要等待较长的网络调用完成所需的时间
如果我在 if 语句中移动 thread2.join() 会发生什么? join 方法可能永远不会被调用。这会导致陈旧的线程等出现一些问题吗?
thread2
仍将继续 运行(根据 GIL 的注意事项,但由于它是网络调用,因此可能不是问题)是否 join
是否被调用。不同之处在于主上下文是否在继续执行其他操作之前等待线程结束 - 如果您能够在没有完成更长的网络调用的情况下继续处理,那么应该没有问题。
请记住,在所有线程完成之前,程序不会真正结束(解释器不会退出)。根据此长网络调用对程序其余部分 运行 时间的延迟(如果您不等待),程序可能看起来已经结束,但实际上并没有退出,直到网络呼叫结束。考虑这个愚蠢的例子:
# Python 2.7
import threading
import time
import logging
def wasteTime(sec):
logging.info('Thread to waste %d seconds started' % sec)
time.sleep(sec)
logging.info('Thread to waste %d seconds ended' % sec)
if __name__ == '__main__':
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
t1 = threading.Thread(target=wasteTime, args=(2,))
t2 = threading.Thread(target=wasteTime, args=(10,))
t1.start()
t2.start()
t1.join()
logging.info('Main context done')
这是日志输出:
$ time python test.py
2015-01-15 09:32:12,239 Thread to waste 2 seconds started
2015-01-15 09:32:12,239 Thread to waste 10 seconds started
2015-01-15 09:32:14,240 Thread to waste 2 seconds ended
2015-01-15 09:32:14,241 Main context done
2015-01-15 09:32:22,240 Thread to waste 10 seconds ended
real 0m10.026s
user 0m0.015s
sys 0m0.010s
请注意,尽管主上下文在 2 秒后(thread1
完成所花费的时间)结束,但程序在 thread2
完成之前不会完全退出(执行开始后十秒)。在这种情况下(特别是如果输出被这样记录),我认为最好在某个时候显式调用 join
并在您的日志中明确标识这是程序正在做的事情,以便在 user/operator 看来它不像挂起的那样。对于我的愚蠢示例,这可能看起来像在主上下文的末尾添加这样的行:
logging.info('Waiting for thread 2 to complete')
t2.join()
这将生成不那么神秘的日志输出:
$ time python test.py
2015-01-15 09:39:18,979 Thread to waste 2 seconds started
2015-01-15 09:39:18,979 Thread to waste 10 seconds started
2015-01-15 09:39:20,980 Thread to waste 2 seconds ended
2015-01-15 09:39:20,980 Main context done
2015-01-15 09:39:20,980 Waiting for thread 2 to complete
2015-01-15 09:39:28,980 Thread to waste 10 seconds ended
real 0m10.027s
user 0m0.015s
sys 0m0.010s