Hone logo
Hone
Problems

Python Threading Basics: Concurrent Task Execution

This challenge will test your understanding of fundamental threading concepts in Python. You will be tasked with creating and managing multiple threads to perform simple operations concurrently. This is a crucial skill for building responsive applications, improving performance by utilizing multi-core processors, and handling I/O-bound tasks efficiently.

Problem Description

Your goal is to write a Python program that demonstrates basic thread creation, execution, and joining. You will create a specified number of threads, each of which will perform a simple task: printing its thread's name and a counter value. After starting all threads, you need to ensure that the main program waits for all of them to complete before exiting.

Key Requirements:

  1. Thread Creation: Create a specific number of threads (configurable).
  2. Thread Function: Each thread will execute a function that:
    • Prints a message indicating its name.
    • Sleeps for a short, random duration to simulate work.
    • Prints a counter value a few times (e.g., 5 times).
  3. Thread Naming: Each thread should be given a unique and descriptive name.
  4. Thread Execution: Start all created threads.
  5. Thread Joining: The main program must wait for all worker threads to finish their execution before proceeding and exiting.
  6. Output Clarity: The output should clearly show which thread is printing and what it's doing.

Expected Behavior:

The output will show messages from different threads intermingled, demonstrating concurrency. The exact order of messages will vary due to the random sleep durations and the nature of thread scheduling. The program should terminate only after all threads have completed their printing and sleeping cycles.

Edge Cases:

  • Zero Threads: What happens if the program is asked to create zero threads?
  • Large Number of Threads: Consider the potential impact of creating a very large number of threads (though performance constraints will limit this).

Examples

Example 1:

Input:
Number of threads: 3
Counter iterations per thread: 5

Output:
Main thread starting...
Thread-1: Starting task.
Thread-2: Starting task.
Thread-3: Starting task.
Thread-1: Iteration 1/5
Thread-2: Iteration 1/5
Thread-3: Iteration 1/5
Thread-1: Iteration 2/5
Thread-3: Iteration 2/5
Thread-2: Iteration 2/5
Thread-1: Iteration 3/5
Thread-3: Iteration 3/5
Thread-2: Iteration 3/5
Thread-1: Iteration 4/5
Thread-3: Iteration 4/5
Thread-2: Iteration 4/5
Thread-1: Iteration 5/5
Thread-3: Iteration 5/5
Thread-2: Iteration 5/5
Thread-1: Task finished.
Thread-2: Task finished.
Thread-3: Task finished.
Main thread finished.

Explanation:

The main thread initiates the process. Three worker threads are created and started. Each thread prints its progress for a set number of iterations, with random delays between them. The intermingled output shows that threads are running concurrently. The "Main thread finished." message appears only after all worker threads have signaled completion.

Example 2:

Input:
Number of threads: 1
Counter iterations per thread: 3

Output:
Main thread starting...
Thread-1: Starting task.
Thread-1: Iteration 1/3
Thread-1: Iteration 2/3
Thread-1: Iteration 3/3
Thread-1: Task finished.
Main thread finished.

Explanation:

With only one thread, the output will appear sequential, as there's no other thread to interleave with. The main thread still waits for this single worker thread to complete.

Constraints

  • The number of threads to create will be an integer between 0 and 20, inclusive.
  • The number of counter iterations per thread will be an integer between 1 and 10, inclusive.
  • The random sleep duration for each iteration will be between 0.1 and 0.5 seconds.
  • Your solution should use Python's built-in threading module.
  • Avoid using multiprocessing or concurrent.futures for this challenge.

Notes

  • You'll need to import the threading and time modules.
  • Consider using threading.Thread to create new threads.
  • The target argument of threading.Thread will be your worker function.
  • The name argument can be used to assign a descriptive name to each thread.
  • Use the start() method to begin a thread's execution.
  • Use the join() method on a thread object to make the calling thread (usually the main thread) wait for it to finish.
  • The time.sleep() function can be used to introduce delays. You might want to use random.uniform() for random sleep durations.
Loading editor...
python