I was studying the python threading and came across
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.
but I have also seen him using
t.join() even though
t was not
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
A somewhat clumsy ascii-art to demonstrate the mechanism:
join() is presumably called by the main-thread. It could also be called by another thread, but would needlessly complicate the diagram.
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.
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
You could say
join is (only) relevant for the execution-flow of the main-thread.
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
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.
This means that the main thread which spawns
d, waits for
t to finish until it finishes.
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.
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
t thread to finish until it calls
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
t thread to finish. In this case we might even remove the explicit joining
t.join() and the program will implicitly wait for
t to finish.