Python线程中join()有什么用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15085348/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the use of join() in Python threading?
提问by user192362127
I was studying the python threading and came across join().
我正在研究 python 线程并遇到了join().
The author told that if thread is in daemon mode then i need to use join()so that thread can finish itself before main thread terminates.
作者告诉我,如果线程处于守护程序模式,那么我需要使用,join()以便线程可以在主线程终止之前完成自己。
but I have also seen him using t.join()even though twas not daemon
但我也看到他使用t.join()即使t不是daemon
example code is this
示例代码是这样的
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()
i don't know what is use of t.join()as it is not daemon and i can see no change even if i remove it
我不知道有什么用,t.join()因为它不是守护进程,即使我删除它我也看不到任何变化
采纳答案by Don Question
A somewhat clumsy ascii-art to demonstrate the mechanism:
The join()is presumably called by the main-thread. It could also be called by another thread, but would needlessly complicate the diagram.
一个有点笨拙的 ascii-art 来演示该机制:join()大概是由主线程调用的。它也可以被另一个线程调用,但会不必要地使图表复杂化。
join-calling should be placed in the track of the main-thread, but to express thread-relation and keep it as simple as possible, I choose to place it in the child-thread instead.
join-calling应该放在主线程的轨道上,但是为了表达线程关系,尽量简单,我选择放在子线程中。
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 daemon thread
+-+--+---+------------------***********+### parent-thread
| | | |
| | +...........join() | child-thread(short)
| +......................join()...... child-thread(long)
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, child-thread(long + daemonized)
'-' 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
',' daemonized thread - 'ignores' lifetime of other threads;
terminates when main-programs exits; is normally meant for
join-independent tasks
So the reason you don't see any changes is because your main-thread does nothing after your join.
You could say joinis (only) relevant for the execution-flow of the main-thread.
所以你没有看到任何变化的原因是因为你的主线程在你的join. 您可以说join(仅)与主线程的执行流程相关。
If, for example, you want to concurrently download a bunch of pages to concatenate them into a single large page, you may start concurrent downloads using threads, but need to wait until the last page/thread is finished before you start assembling a single page out of many. That's when you use join().
例如,如果您想同时下载一堆页面以将它们连接成一个大页面,您可以使用线程开始并发下载,但需要等到最后一个页面/线程完成后再开始组装单个页面在许多。那就是当你使用join().
回答by Ketouem
The method join()
方法 join()
blocks the calling thread until the thread whose join() method is called is terminated.
阻塞调用线程,直到调用其 join() 方法的线程终止。
回答by dmg
Straight from the docs
直接来自文档
join([timeout]) Wait until the thread terminates. This blocks the calling thread until the thread whose join() method is called terminates – either normally or through an unhandled exception – or until the optional timeout occurs.
join([timeout]) 等到线程终止。这会阻塞调用线程,直到调用其 join() 方法的线程终止 - 正常或通过未处理的异常 - 或直到发生可选超时。
This means that the main thread which spawns tand d, waits for tto finish until it finishes.
这意味着产生tand的主线程d等待t完成直到完成。
Depending on the logic your program employs, you may want to wait until a thread finishes before your main thread continues.
根据您的程序采用的逻辑,您可能希望在主线程继续之前等待线程完成。
Also from the docs:
也来自文档:
A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left.
一个线程可以被标记为“守护线程”。这个标志的意义在于,当只剩下守护线程时,整个 Python 程序就会退出。
A simple example, say we have this:
一个简单的例子,假设我们有这个:
def non_daemon():
time.sleep(5)
print 'Test non-daemon'
t = threading.Thread(name='non-daemon', target=non_daemon)
t.start()
Which finishes with:
结束于:
print 'Test one'
t.join()
print 'Test two'
This will output:
这将输出:
Test one
Test non-daemon
Test two
Here the master thread explicitly waits for the tthread to finish until it calls printthe second time.
这里主线程显式地等待t线程完成,直到它print第二次调用。
Alternatively if we had this:
或者,如果我们有这个:
print 'Test one'
print 'Test two'
t.join()
We'll get this output:
我们会得到这个输出:
Test one
Test two
Test non-daemon
Here we do our job in the main thread and then we wait for the tthread to finish. In this case we might even remove the explicit joining t.join()and the program will implicitly wait for tto finish.
在这里,我们在主线程中完成我们的工作,然后我们等待t线程完成。在这种情况下,我们甚至可能删除显式连接t.join(),程序将隐式等待t完成。
回答by user1342336
When making join(t)function for both non-daemon thread and daemon thread, the main thread (or main process) should wait tseconds, then can go further to work on its own process. During the tseconds waiting time, both of the children threads should do what they can do, such as printing out some text. After the tseconds, if non-daemon thread still didn't finish its job, and it still can finish it after the main process finishes its job, but for daemon thread, it just missed its opportunity window. However, it will eventually die after the python program exits. Please correct me if there is something wrong.
在join(t)为非守护线程和守护线程创建函数时,主线程(或主进程)应该等待t几秒钟,然后可以进一步在自己的进程上工作。在t几秒钟的等待时间内,两个子线程都应该做他们能做的事情,比如打印一些文本。在后t秒,如果非守护线程仍然没有完成其工作,其主要过程完成其工作后仍可以完成,但对于守护线程,它只是错过了机会之窗。但是最终会在python程序退出后死亡。如果有什么不对的地方,请纠正我。
回答by Chris Cogdon
"What's the use of using join()?" you say. Really, it's the same answer as "what's the use of closing files, since python and the OS will close my file for me when my program exits?".
“使用join()有什么用?” 你说。真的,这与“关闭文件有什么用,因为当我的程序退出时python和操作系统会为我关闭我的文件?”的答案相同。
It's simply a matter of good programming. You should join() your threads at the point in the code that the thread should notbe running anymore, either because you positively have to ensure the thread is not running to interfere with your own code, or that you want to behave correctly in a larger system.
这只是一个好的编程问题。您应该在代码中线程不应再运行的点加入()您的线程,因为您肯定必须确保线程不会运行以干扰您自己的代码,或者您希望在更大的系统。
You might say "I don't want my code to delay giving an answer" just because of the additional time that the join() might require. This may be perfectly valid in some scenarios, but you now need to take into account that your code is "leaving cruft around for python and the OS to clean up". If you do this for performance reasons, I strongly encourage you to document that behavior. This is especially true if you're building a library/package that others are expected to utilize.
您可能会说“我不希望我的代码延迟给出答案”只是因为 join() 可能需要额外的时间。这在某些情况下可能是完全有效的,但您现在需要考虑到您的代码“为 python 和操作系统留下了要清理的余地”。如果您出于性能原因这样做,我强烈建议您记录该行为。如果您正在构建其他人希望使用的库/包,则尤其如此。
There's no reason to not join(), other than performance reasons, and I would argue that your code does not need to perform thatwell.
除了性能原因之外,没有理由不使用 join(),我认为您的代码不需要执行得那么好。
回答by Kiki Jewell
Thanks for this thread -- it helped me a lot too.
感谢这个线程——它对我也有很大帮助。
I learned something about .join() today.
我今天学到了一些关于 .join() 的知识。
These threads run in parallel:
这些线程并行运行:
d.start()
t.start()
d.join()
t.join()
and these run sequentially (not what I wanted):
这些按顺序运行(不是我想要的):
d.start()
d.join()
t.start()
t.join()
In particular, I was trying to clever and tidy:
特别是,我试图巧妙而整洁:
class Kiki(threading.Thread):
def __init__(self, time):
super(Kiki, self).__init__()
self.time = time
self.start()
self.join()
This works! But it runs sequentially. I can put the self.start() in __ init __, but not the self.join(). That has to be done afterevery thread has been started.
这有效!但它是按顺序运行的。我可以将 self.start() 放在 __ init __ 中,但不能放在 self.join() 中。这必须在每个线程启动后完成。
join() is what causes the main thread to wait for your thread to finish. Otherwise, your thread runs all by itself.
join() 是导致主线程等待线程完成的原因。否则,您的线程将自行运行。
So one way to think of join() as a "hold" on the main thread -- it sort of de-threads your thread and executes sequentially in the main thread, before the main thread can continue. It assures that your thread is complete before the main thread moves forward. Note that this means it's ok if your thread is already finished before you call the join() -- the main thread is simply released immediately when join() is called.
因此,将 join() 视为主线程上的“保持”的一种方法 - 在主线程可以继续之前,它使您的线程脱离线程并在主线程中按顺序执行。它确保您的线程在主线程向前移动之前完成。请注意,这意味着如果您的线程在调用 join() 之前已经完成是可以的——当调用 join() 时,主线程会立即释放。
In fact, it just now occurs to me that the main thread waits at d.join() until thread d finishes before it moves on to t.join().
事实上,我现在才发现主线程在 d.join() 处等待,直到线程 d 完成,然后才移动到 t.join()。
In fact, to be very clear, consider this code:
实际上,要非常清楚,请考虑以下代码:
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"
It produces this output (note how the print statements are threaded into each other.)
它产生这个输出(注意打印语句是如何相互连接的。)
$ 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
$
The t1.join() is holding up the main thread. All three threads complete before the t1.join() finishes and the main thread moves on to execute the print then t2.join() then print then t3.join() then print.
t1.join() 正在阻止主线程。所有三个线程在 t1.join() 完成之前完成,主线程继续执行打印,然后是 t2.join(),然后是打印,然后是 t3.join(),然后是打印。
Corrections welcome. I'm also new to threading.
欢迎指正。我也是线程的新手。
(Note: in case you're interested, I'm writing code for a DrinkBot, and I need threading to run the ingredient pumps concurrently rather than sequentially -- less time to wait for each drink.)
(注意:如果您有兴趣,我正在为 DrinkBot 编写代码,我需要线程来同时而不是按顺序运行成分泵——减少等待每次饮料的时间。)
回答by Benyamin Jafari
This example demonstrate the .join()action:
此示例演示了该.join()操作:
import threading
import time
def threaded_worker():
for r in range(10):
print('Other: ', r)
time.sleep(2)
thread_ = threading.Timer(1, threaded_worker)
thread_.daemon = True # If the main thread kills, this thread will be killed too.
thread_.start()
flag = True
for i in range(10):
print('Main: ', i)
time.sleep(2)
if flag and i > 4:
print(
'''
Threaded_worker() joined to the main thread.
Now we have a sequential behavior instead of concurrency.
''')
thread_.join()
flag = False
Out:
出去:
Main: 0
Other: 0
Main: 1
Other: 1
Main: 2
Other: 2
Main: 3
Other: 3
Main: 4
Other: 4
Main: 5
Other: 5
Threaded_worker() joined to the main thread.
Now we have a sequential behavior instead of concurrency.
Other: 6
Other: 7
Other: 8
Other: 9
Main: 6
Main: 7
Main: 8
Main: 9
回答by Shishir Nanoty
In python 3.x join() is used to join a thread with the main thread i.e. when join() is used for a particular thread the main thread will stop executing until the execution of joined thread is complete.
在python 3.x 中,join() 用于将线程与主线程连接,即当join() 用于特定线程时,主线程将停止执行,直到连接线程的执行完成。
#1 - Without Join():
import threading
import time
def loiter():
print('You are loitering!')
time.sleep(5)
print('You are not loitering anymore!')
t1 = threading.Thread(target = loiter)
t1.start()
print('Hey, I do not want to loiter!')
'''
Output without join()-->
You are loitering!
Hey, I do not want to loiter!
You are not loitering anymore! #After 5 seconds --> This statement will be printed
'''
#2 - With Join():
import threading
import time
def loiter():
print('You are loitering!')
time.sleep(5)
print('You are not loitering anymore!')
t1 = threading.Thread(target = loiter)
t1.start()
t1.join()
print('Hey, I do not want to loiter!')
'''
Output with join() -->
You are loitering!
You are not loitering anymore! #After 5 seconds --> This statement will be printed
Hey, I do not want to loiter!
'''
回答by Mohideen bin Mohammed
Simple Understand,
简单理解,
with join - interpreter will wait until your process get completedor terminated
with join - 解释器将等到您的进程完成或终止
>>> from threading import Thread
>>> import time
>>> def sam():
... print 'started'
... time.sleep(10)
... print 'waiting for 10sec'
...
>>> t = Thread(target=sam)
>>> t.start()
started
>>> t.join() # with join interpreter will wait until your process get completed or terminated
done? # this line printed after thread execution stopped i.e after 10sec
waiting for 10sec
>>> done?
without join - interpreter wont wait until process get terminated,
没有加入 - 解释器不会等到进程终止,
>>> t = Thread(target=sam)
>>> t.start()
started
>>> print 'yes done' #without join interpreter wont wait until process get terminated
yes done
>>> waiting for 10sec
回答by yoonghm
There are a few reasons for the main thread (or any other thread) to join other threads
主线程(或任何其他线程)加入其他线程有几个原因
A thread may have created or holding (locking) some resources. The join-calling thread may be able to clear the resources on its behalf
join() is a natural blocking call for the join-calling thread to continue after the called thread has terminated.
一个线程可能已经创建或持有(锁定)了一些资源。连接调用线程可能能够代表它清除资源
join() 是一个自然的阻塞调用,用于在被调用线程终止后继续调用连接调用线程。
If a python program does not join other threads, the python interpreter will still join non-daemon threads on its behalf.
如果一个python程序没有加入其他线程,python解释器仍然会代表它加入非守护线程。

