"Is there a way to terminate the the first cycle of threads after joining" - joining is the same as terminating, though. the_thread.name looks like 'Thread-N', where N is the "number" of a thread, which is normally increased for each new thread. This doesn't necessarily mean that if this thread is 'Thread-100', then the previous 99 threads are still running.
Joining a thread means terminating it, so no stray threads will be left running.
Example
>>> import threading, time
>>> th = threading.Thread(target=lambda: time.sleep(10))
>>> th.start(); th.join()
>>> th.is_alive()
False # the thread is dead
>>> th.name
'Thread-1'
>>> th2 = threading.Thread(target=lambda: time.sleep(10))
>>> th2.start(); th2.join()
>>> th2.is_alive(), th2.name
(False, 'Thread-2') # This thread is dead alongside Thread-1
>>>
You can test it by looking at how many threads your Python process has (in Task manager or maybe something like top):
Create a thread that just hangs there for some time:
th = threading.Thread(target=lambda: time.sleep(10))
Start the thread and wait for it: th.start(); th.join()
While the thread is running, quickly locate the Python process in Task manager
It should have 2 OS threads running (Python actually creates OS threads for each running threading.Thread!)
Once the thread exits, the Python process will have only one OS thread - the main interpreter thread.
Thus, the thread you created terminated.
is_aliveis reset to False —when it’srunmethod terminates. Without a timeout, ajoinis guaranteed to wait for this condition and the thread is “no longer alive” and the actual Python thread wrapper object follows normal lifetime (and GC) rules.)