python线程中join()的用法是什么?
我正在研究python线程,并遇到了join()
。
作者告诉说,如果线程处于守护进程模式,那么我需要使用join()
以便在主线程终止之前线程可以完成自己的工作。
但是我也看到他使用t.join()
即使t
不是daemon
示例代码是这样的
import threading import time import logging logging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s) %(message)s', ) def daemon(): logging.debug('Starting') time.sleep(2) logging.debug('Exiting') d = threading.Thread(name='daemon', target=daemon) d.setDaemon(True) def non_daemon(): logging.debug('Starting') logging.debug('Exiting') t = threading.Thread(name='non-daemon', target=non_daemon) d.start() t.start() d.join() t.join()
我不知道什么是t.join()
因为它不是守护进程,我可以看到没有变化,即使我删除它
一个有点笨拙的ascii艺术来演示机制: join()
大概是由主线程调用的。 它也可以被另一个线程调用,但会不必要地使图变复杂。
join
-calling应该放在主线程的轨道上,但为了expression线程关系并尽可能保持简单,我select把它放在子线程中。
without join: +---+---+------------------ main-thread | | | +........... child-thread(short) +.................................. child-thread(long) with join +---+---+------------------***********+### main-thread | | | | +...........join() | child-thread(short) +......................join()...... child-thread(long) with join and demon thread +-+--+---+------------------***********+### parent-thread | | | | | | +...........join() | child-thread(short) | +......................join()...... child-thread(long) +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, child-thread(long+demonized) '-' main-thread/parent-thread/main-program execution '.' child-thread execution '#' optional parent-thread execution after join()-blocked parent-thread could continue '*' main-thread 'sleeping' in join-method, waiting for child-thread to finish ',' demonized thread - 'ignores' lifetime of other threads; terminates when main-programs exits; is normally meant for join-independent tasks
所以你没有看到任何改变的原因是因为你的主线程在你的join
之后什么都不做。 你可以说join
(仅)与主线程的执行stream程相关。
例如,如果您想要同时下载一堆页面以将它们连接成一个大页面,则可以使用线程开始并发下载,但是在开始组装单页面之前需要等到最后一页/线程完成出了很多 那是你使用join()
。
直接从文档
join([timeout])等到线程终止。 这将阻塞调用线程,直到调用join()方法的线程终止 – 通常或通过未处理的exception – 或直到发生可选的超时。
这意味着产生t
和d
的主线程等待t
完成。
根据您的程序使用的逻辑,您可能需要等到某个线程完成后再继续主线程。
另外从文档:
一个线程可以被标记为“守护线程”。 这个标志的意义在于,只有守护进程线程被留下时,整个Python程序才会退出。
一个简单的例子,说我们有这个:
def non_daemon(): time.sleep(5) print 'Test non-daemon' t = threading.Thread(name='non-daemon', target=non_daemon) t.start()
结束于:
print 'Test one' t.join() print 'Test two'
这将输出:
Test one Test non-daemon Test two
这里主线程显式等待t
线程完成,直到第二次调用print
。
或者,如果我们有这个:
print 'Test one' print 'Test two' t.join()
我们会得到这个输出:
Test one Test two Test non-daemon
在这里,我们在主线程中执行我们的工作,然后等待t
线程完成。 在这种情况下,我们甚至可能删除显式的joint.join()
,程序将隐式等待t
完成。
join()方法
阻塞调用线程,直到join()方法被调用的线程终止。
资料来源: http : //docs.python.org/2/library/threading.html
感谢这个线程 – 它也帮了我很多。
我今天学到了一些关于.join()的东西。
这些线程并行运行:
d.start() t.start() d.join() t.join()
这些按顺序运行(不是我想要的):
d.start() d.join() t.start() t.join()
特别是,我试图聪明和整齐:
class Kiki(threading.Thread): def __init__(self, time): super(Kiki, self).__init__() self.time = time self.start() self.join()
这工作! 但它依次运行。 我可以把self.start()放在__ init __中,而不是self.join()。 这必须在每个线程启动后完成。
join()是什么导致主线程等待你的线程完成。 否则,你的线程自行运行。
所以有一种方法可以将join()看作是主线程中的一个“保留”,它可以在主线程继续执行之前,对主线程中的线程进行解线程并按顺序执行。 它确保您的线程在主线程向前移动之前完成。 请注意,这意味着在调用join()之前,如果线程已经完成,那么主线程在调用join()时会立即释放。
实际上,现在刚刚发生的事情是,主线程在d.join()等待,直到线程d完成,然后移动到t.join()。
其实要非常清楚,请考虑下面的代码:
import threading import time class Kiki(threading.Thread): def __init__(self, time): super(Kiki, self).__init__() self.time = time self.start() def run(self): print self.time, " seconds start!" for i in range(0,self.time): time.sleep(1) print "1 sec of ", self.time print self.time, " seconds finished!" t1 = Kiki(3) t2 = Kiki(2) t3 = Kiki(1) t1.join() print "t1.join() finished" t2.join() print "t2.join() finished" t3.join() print "t3.join() finished"
它产生这个输出(注意打印语句是如何相互连接的)。
$ python test_thread.py 32 seconds start! seconds start!1 seconds start! 1 sec of 1 1 sec of 1 seconds finished! 21 sec of 3 1 sec of 3 1 sec of 2 2 seconds finished! 1 sec of 3 3 seconds finished! t1.join() finished t2.join() finished t3.join() finished $
t1.join()保持主线程。 所有三个线程在t1.join()完成之前完成并且主线程继续执行打印,然后t2.join()然后打印,然后t3.join()然后打印。
更正欢迎。 我也是线程新手。
(注意:如果您有兴趣,我正在为DrinkBot编写代码,而且我需要线程来同时运行配料泵,而不是按顺序运行,而不是等待每个饮料的时间。
当为非守护线程和守护线程build立join(t)函数时,主线程(或主进程)应该等待t秒,然后才能进一步处理它自己的进程。 在t秒的等待时间内,两个子线程都应该做他们能做的事情,比如打印一些文本。 在t秒之后,如果非守护线程仍然没有完成工作,并且在主进程完成工作之后仍然可以完成它,但是对于守护进程线程,它只是错过了它的机会窗口。 但是在python程序退出后,它最终会死掉。 如果有什么问题,请纠正我。
“使用join()有什么用?” 你说。 真的,这和“closures文件有什么关系,因为当我的程序退出时,python和操作系统会为我closures文件”。
这只是一个好的编程问题。 你应该join()你的线程在线程不应该再运行的代码点,要么因为你肯定要确保线程没有运行来干扰你自己的代码,要么你想在一个正确的行为更大的系统。
你可能会说“我不想让我的代码延迟给出答案”,因为join()可能需要额外的时间。 在某些情况下,这可能是完全有效的,但是现在需要考虑到你的代码是“为python和操作系统清理”。 如果您出于性能原因这样做,我强烈build议您logging该行为。 如果您正在构build其他人需要使用的库/软件包,则更是如此。
没有理由不join(),除了性能的原因,我会争辩说,你的代码不需要执行得很好。