How to Pause and Resume Threads with threading.Event in Python
Use threading.Event to pause and resume worker threads in Python, controlling execution flow with set and clear methods.
Python code
48 linesimport threading
import time
workers = []
def worker(name, event):
for i in range(10):
event.wait()
print(f"{name} step {i}")
time.sleep(0.1)
def pause_worker(name):
global pause_event
for w in workers:
if w.name == name:
pause_event.clear()
print(f"{name} paused")
def resume_worker(name):
global pause_event
for w in workers:
if w.name == name:
pause_event.set()
print(f"{name} resumed")
if __name__ == "__main__":
pause_event = threading.Event()
pause_event.set()
t1 = threading.Thread(target=worker, args=("A", pause_event), name="A")
workers.append(t1)
t2 = threading.Thread(target=worker, args=("B", pause_event), name="B")
workers.append(t2)
t1.start()
t2.start()
time.sleep(0.3)
pause_worker("A")
time.sleep(0.5)
resume_worker("A")
time.sleep(0.3)
pause_worker("A")
time.sleep(0.3)
resume_worker("A")
t1.join()
t2.join()
Output
A step 0
B step 0
A step 1
B step 1
A step 2
B step 2
A step 3
B step 3
A paused
B step 4
B step 5
B step 6
B step 7
A resumed
A step 4
B step 8
A step 5
B step 9
A step 6
A paused
A step 7
A resumed
A step 8
A step 9
How it works
The threading.Event object acts as a simple flag that threads can check with wait(). When the event is set, wait() returns immediately, allowing the worker to proceed; when cleared, wait() blocks the thread until the event is set again. The main thread controls the event by calling clear() to pause and set() to resume, affecting only the target worker because each worker uses its own event instance. The sleep calls in the main thread give a deterministic sequence for demonstration, but in real code you'd use condition variables or queues for more complex coordination.
Common mistakes
- Using `event.wait()` without a timeout can hang threads if the event is never set again.
- Modifying a global event from multiple threads without synchronization can cause race conditions.
- Assuming `clear()` instantly stops a thread mid-iteration; it only blocks at the next `wait()` call.
- Forgetting to set the event initially before starting threads, causing them to block immediately.
Variations
- Use `threading.Condition` to wait for specific conditions and notify specific threads.
- Use a `queue.Queue` with sentinel values to control worker shutdown or pausing in a producer-consumer pattern.
Real-world use cases
- Pausing a background data-sync worker when the network is down and resuming when connectivity returns.
- Throttling CPU-intensive tasks during peak hours by pausing worker threads until off-peak time.
- Coordinating multiple threads in a simulation to advance only when the main thread gives a go-ahead signal.
Sponsored
More from Concurrency & performance
- Benchmark list.append vs deque.append in Python medium
- Build a Python Performance Profiler That Generates Readable Reports medium
- Graceful Shutdown Executor Context Manager in Python medium
- How to Build a Producer-Consumer Pattern with asyncio.Queue in Python medium
- How to Cancel an asyncio Task with Graceful Cleanup in Python medium
- How to Convert Data in Parallel with ThreadPoolExecutor in Python easy
Keep learning
Related tutorials and quizzes for this topic.