When working with multiple threads we need to ensure that the main program waits until all spawned threads have completed their tasks. In this article, we will see how to ensure all threads are finished before the main program terminates.

Using join() Method

Using the join() method, we can wait for a thread to complete. This method blocks the calling thread (Here main method) until the thread whose join() method called is terminated.

Following is the example:

import threading
import time

def worker():
    print("Thread is starting")
    time.sleep(2)  # Simulate a task taking some time
    print("Thread is finishing")

# Create threads
threads = []
for i in range(5):
    thread = threading.Thread(target=worker)

# Wait for all threads to complete
for thread in threads:

print("All threads have finished.")

In the above example, five worker threads are created. The main thread waits for each of the spawned threads to complete by calling join() on each thread.

Using a ThreadPoolExecutor

Using the python’s concurrent.futures module we can manage a pool of threads. This module provides the ThreadPoolExecutor, which simplifies thread management and provides an easy way to wait for all threads to complete.

Following is the example of ThreadPoolExecutor

import concurrent.futures

def worker():
    print("Thread is starting")
    print("Thread is finishing")
    return "Done"

# Create a ThreadPoolExecutor
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    futures = [executor.submit(worker) for _ in range(5)]
    for future in concurrent.futures.as_completed(futures):

print("All threads have finished.")

In the above example, the ThreadPoolExecutor manages a pool of five worker threads. The submit() method schedules the worker function to be executed and returns a future object. The as_completed() yields futures when the spawned threads finish the execution.

Categorized in:

Tagged in: