在python线程中使用join()有什么用处

use*_*127 167 python multithreading python-multithreading

我正在研究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()
Run Code Online (Sandbox Code Playgroud)

我不知道什么是使用,t.join()因为它不是守护进程,即使我删除它我也看不到任何变化

Don*_*ion 250

有点笨拙的ascii-art来演示机制:join()可能是主线程调用的.它也可以被另一个线程调用,但会不必要地使图复杂化.

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
Run Code Online (Sandbox Code Playgroud)

因此,您没有看到任何更改的原因是因为您的主线程在您的后面没有任何作用join.你可以说join(仅)与主线程的执行流程相关.

例如,如果您想同时下载一堆页面以将它们连接成一个大页面,您可以使用线程开始并发下载,但需要等到最后一页/线程完成后再开始组装单个页面很多人 那是你用的时候join().


dmg*_*dmg 59

直接来自文档

join([timeout])等待线程终止.这会阻塞调用线程,直到调用join()方法的线程终止 - 正常或通过未处理的异常 - 或直到发生可选的超时.

这意味着产生td等待t完成的主线程完成.

根据程序使用的逻辑,您可能希望等到主线程继续之前线程完成.

同样来自文档:

线程可以标记为"守护程序线程".这个标志的意义在于,当只剩下守护进程线程时,整个Python程序都会退出.

一个简单的例子,说我们有这个:

def non_daemon():
    time.sleep(5)
    print 'Test non-daemon'

t = threading.Thread(name='non-daemon', target=non_daemon)

t.start()
Run Code Online (Sandbox Code Playgroud)

哪个完成:

print 'Test one'
t.join()
print 'Test two'
Run Code Online (Sandbox Code Playgroud)

这将输出:

Test one
Test non-daemon
Test two
Run Code Online (Sandbox Code Playgroud)

这里主线程显式等待t线程完成,直到它print第二次调用.

或者,如果我们有这个:

print 'Test one'
print 'Test two'
t.join()
Run Code Online (Sandbox Code Playgroud)

我们将得到这个输出:

Test one
Test two
Test non-daemon
Run Code Online (Sandbox Code Playgroud)

在这里,我们在主线程中完成工作,然后等待t线程完成.在这种情况下,我们甚至可以删除显式连接t.join(),程序将隐式等待t完成.


Kik*_*ell 30

感谢这个帖子 - 它也帮助了我很多.

我今天学到了关于.join()的一些知识.

这些线程并行运行:

d.start()
t.start()
d.join()
t.join()
Run Code Online (Sandbox Code Playgroud)

这些顺序运行(不是我想要的):

d.start()
d.join()
t.start()
t.join()
Run Code Online (Sandbox Code Playgroud)

特别是,我试图聪明和整洁:

class Kiki(threading.Thread):
    def __init__(self, time):
        super(Kiki, self).__init__()
        self.time = time
        self.start()
        self.join()
Run Code Online (Sandbox Code Playgroud)

这有效!但它按顺序运行.我可以将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"
Run Code Online (Sandbox Code Playgroud)

它产生这个输出(注意print语句是如何相互连接的.)

$ 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
$ 
Run Code Online (Sandbox Code Playgroud)

t1.join()正在阻止主线程.所有三个线程在t1.join()完成之前完成,主线程继续执行print然后t2.join()然后打印然后t3.join()然后打印.

更正欢迎.我也是线程新手.

(注意:如果您感兴趣,我正在为DrinkBot编写代码,我需要线程同时运行配料泵而不是顺序运行 - 减少等待每种饮料的时间.)

  • 主线程是程序本身。每个线程都是从那里分叉出来的。然后它们会重新连接起来——因为在命令 join() 处,程序会等待线程完成,然后再继续执行。 (2认同)

Ket*_*uem 15

方法join()

阻塞调用线程,直到调用其join()方法的线程终止.

资料来源:http://docs.python.org/2/library/threading.html

  • 那么加入的用途是什么?看OP问题,不要只是解释文档 (14认同)
  • "加入"和"阻止"术语令人费解."被阻止"表示调用进程被"阻止"执行它仍然必须做的任何事情,而事实上它只是被阻止终止(返回操作系统),而不是更多.出于同样的原因,有一个主线程调用子线程来"加入"它(即终止)并不是那么明显.所以,Don Q,谢谢你的解释. (2认同)

Moh*_*med 9

使用 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?
Run Code Online (Sandbox Code Playgroud)

没有 join - 解释器不会等到进程终止

>>> t = Thread(target=sam)
>>> t.start()
started
>>> print 'yes done' #without join interpreter wont wait until process get terminated
yes done
>>> waiting for 10sec
Run Code Online (Sandbox Code Playgroud)


Ben*_*ari 6

此示例演示了该.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 is killed, this thread will be killed as well. 
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
Run Code Online (Sandbox Code Playgroud)

出去:

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
Run Code Online (Sandbox Code Playgroud)


小智 5

在 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! 

'''
Run Code Online (Sandbox Code Playgroud)