why should you join thread python code example

Example: thread join python

'''
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
    
---------------------------------------------------------

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 print the second time.

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'''