CyclicBarrier in Java – Complete Guide with Real-World Example, Execution Flow, and Code
When building multithreaded applications in Java, it is common to divide a large task into smaller parts and let multiple threads process those parts simultaneously. This improves performance…
When building multithreaded applications in Java, it is common to divide a large task into smaller parts and let multiple threads process those parts simultaneously. This improves performance because multiple CPU cores can work on different pieces of the task at the same time.
However, many real-world applications involve multiple processing stages. Before moving to the next stage, all threads must finish the current stage. For example, in an e-commerce application, all product prices must be calculated before inventory is updated. If one thread starts updating stock while another is still calculating prices, the data may become inconsistent.
This is exactly the problem that CyclicBarrier solves.
CyclicBarrier is a synchronization utility introduced in Java 5 as part of the java.util.concurrent package. It allows multiple threads to wait for each other at a common point called a barrier. Once all participating threads reach the barrier, they are released together and continue to the next phase.
Unlike CountDownLatch, a CyclicBarrier can be reused multiple times, making it ideal for applications that process work in multiple phases.
In this article, you will learn what CyclicBarrier is, how it works internally, its execution flow, practical use cases, complete code examples, interview questions, and the differences between CyclicBarrier and CountDownLatch.
What is CyclicBarrier?
CyclicBarrier is a synchronization utility that allows a fixed number of threads to wait for each other until all threads complete the current phase of execution. Once every thread reaches the barrier, the barrier opens automatically, allowing all threads to continue together.
The word Cyclic means that the same barrier can be used repeatedly for multiple phases of work.
Why Do We Need CyclicBarrier?
Imagine an application processing 1 million products.
The work is divided among four worker threads.
Worker 1 → Products 1 - 250,000
Worker 2 → Products 250,001 - 500,000
Worker 3 → Products 500,001 - 750,000
Worker 4 → Products 750,001 - 1,000,000
Each worker performs three phases.
Phase 1
- Calculate Price
- Apply Discount
- Calculate Tax
Phase 2
- Update Inventory
Phase 3
- Generate Report
Suppose Worker 3 finishes price calculation much earlier than Worker 4.
Should Worker 3 immediately update inventory?
No.
Inventory should only be updated after every worker has completed price calculation.
This synchronization point is exactly what CyclicBarrier provides.
Execution Flow
Phase 1
Worker1 ───────────────┐
Worker2 ───────────────┤
Worker3 ───────────────┤
Worker4 ───────────────┘
WAIT HERE
=================
CyclicBarrier
=================
Phase 2
Worker1 ───────────────┐
Worker2 ───────────────┤
Worker3 ───────────────┤
Worker4 ───────────────┘
WAIT AGAIN
=================
Same Barrier Reused
=================
Phase 3
Worker1
Worker2
Worker3
Worker4
Notice that the same barrier is reused after every phase.
How Does CyclicBarrier Work?
Suppose we create a barrier for four threads.
CyclicBarrier barrier = new CyclicBarrier(4);
The execution happens like this.
Thread 1 finishes Phase 1
↓
barrier.await()
↓
WAIT
Thread 2 finishes Phase 1
↓
barrier.await()
↓
WAIT
Thread 3 finishes Phase 1
↓
barrier.await()
↓
WAIT
Thread 4 finishes Phase 1
↓
barrier.await()
↓
Barrier Opens
↓
All Threads Continue Together
The first three threads remain blocked until the fourth thread reaches the barrier.
The await() Method
The most important method of CyclicBarrier is:
barrier.await();
It means:
“I have completed my current phase. I will wait here until all participating threads also complete this phase.”
When the required number of threads arrive, the barrier automatically opens.
Creating a CyclicBarrier
Basic syntax:
CyclicBarrier barrier = new CyclicBarrier(numberOfThreads);
Example:
CyclicBarrier barrier = new CyclicBarrier(3);
Three worker threads must call await() before anyone continues.
Barrier Action
Sometimes you want to execute one task after every thread reaches the barrier.
For example:
- Print progress
- Merge intermediate results
- Log completion
- Validate data
You can provide a barrier action.
CyclicBarrier barrier =
new CyclicBarrier(3,
() -> System.out.println("All workers completed this phase."));
The barrier action executes once, just before the waiting threads continue.
Complete Example
import java.util.concurrent.*;
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(
3,
() -> System.out.println("\nAll workers completed this phase.\n")
);
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 1; i <= 3; i++) {
int workerId = i;
executor.submit(() -> {
try {
// Phase 1
System.out.println("Worker " + workerId + " completed Price Calculation");
Thread.sleep((long)(Math.random() * 2000));
barrier.await();
// Phase 2
System.out.println("Worker " + workerId + " completed Stock Update");
Thread.sleep((long)(Math.random() * 2000));
barrier.await();
// Phase 3
System.out.println("Worker " + workerId + " generated Report");
} catch (Exception e) {
e.printStackTrace();
}
});
}
executor.shutdown();
}
}
Sample Output
Worker 1 completed Price Calculation
Worker 3 completed Price Calculation
Worker 2 completed Price Calculation
All workers completed this phase.
Worker 2 completed Stock Update
Worker 1 completed Stock Update
Worker 3 completed Stock Update
All workers completed this phase.
Worker 2 generated Report
Worker 3 generated Report
Worker 1 generated Report
Notice that no thread starts Phase 2 until all threads complete Phase 1.
Step-by-Step Execution
Step 1
All workers calculate prices.
Worker 1
Worker 2
Worker 3
↓
barrier.await()
All workers wait.
Step 2
The last worker reaches the barrier.
Worker 3
↓
Barrier Opens
Step 3
All workers start inventory update together.
Worker 1
Worker 2
Worker 3
↓
barrier.await()
Again everyone waits.
Step 4
Barrier opens again.
All workers generate reports.
Real-World Use Cases
1. E-commerce Batch Processing
Phase 1
- Calculate prices
Phase 2
- Update inventory
Phase 3
- Refresh search index
2. Image Processing
Phase 1
Split image into multiple parts.
Phase 2
Apply filters.
Phase 3
Merge processed images.
3. Scientific Simulations
Each thread calculates a part of the simulation.
All results must finish before moving to the next iteration.
4. Game Development
Every player thread updates its position.
After every player finishes,
- Detect collisions
- Update scores
- Start next frame
5. Machine Learning
Different threads train different portions of data.
Once everyone finishes,
Combine gradients before starting the next epoch.
Advantages of CyclicBarrier
- Easy thread synchronization.
- Reusable across multiple phases.
- Prevents inconsistent processing.
- Supports barrier actions.
- Suitable for parallel algorithms.
Limitations
- Number of participating threads is fixed.
- If one thread never reaches the barrier, others remain blocked.
- If one thread is interrupted, the barrier becomes broken and waiting threads receive an exception.
CyclicBarrier vs CountDownLatch
| Feature | CountDownLatch | CyclicBarrier |
|---|---|---|
| Reusable | No | Yes |
| Counter resets | No | Yes |
| Waiting Threads | One or more threads wait | All participating threads wait |
| Best For | Waiting for independent tasks | Multi-phase processing |
| Barrier Action | No | Yes |
When Should You Use CyclicBarrier?
Use CyclicBarrier when:
- Multiple threads perform the same task in stages.
- Every thread must finish one stage before the next stage begins.
- The synchronization point must be reused multiple times.
- All participating threads depend on each other before continuing.
Avoid CyclicBarrier when you only need to wait once for background tasks to complete. In those situations, CountDownLatch is usually a better choice.
Frequently Asked Interview Questions
What is CyclicBarrier?
It is a synchronization utility that allows multiple threads to wait for each other at a common barrier before continuing execution.
Why is it called “Cyclic”?
Because the same barrier is automatically reset after all threads cross it and can be reused for the next phase.
Which method blocks the thread?
await()
What happens when the last thread reaches the barrier?
The optional barrier action executes (if provided), the barrier opens, and all waiting threads continue together.
Can CyclicBarrier be reused?
Yes. That is its biggest advantage over CountDownLatch.
Can one thread cross the barrier alone?
No.
Every participating thread must reach the barrier before anyone proceeds.
Conclusion
CyclicBarrier is one of Java’s most useful synchronization utilities for coordinating multiple threads across repeated phases of work. It ensures that no thread moves ahead until every participating thread has completed the current stage, making it ideal for batch processing, scientific computing, simulations, image processing, and multi-stage enterprise workflows.
Whenever your application requires “all threads finish this phase before anyone starts the next one,” CyclicBarrier is the right tool. By combining await(), reusable synchronization, and optional barrier actions, it helps build safe, efficient, and well-coordinated concurrent applications.