The Exchanger class is a synchronization utility provided in the java.util.concurrent package that allows two threads to exchange data objects at a common synchronization point. Each thread sends an object to the other thread and receives an object in return. Both threads must reach the exchange point before the data swap occurs.
Key Points: • Exchanger enables direct data exchange between two threads. • Both threads must arrive at the exchange point for the exchange to happen. • It is useful for producer-consumer style communication. • Exchanger is part of the java.util.concurrent package. • The exchange() method blocks until the partner thread arrives.
How Does Exchanger Work?
An Exchanger acts like a meeting point for two threads.
Thread A:
Provides Object A
Thread B:
Provides Object B
After exchange:
Thread A receives Object B
Thread B receives Object A
Flow:
Thread A | exchange() | <---- Data Swap ----> | Thread B
Both threads continue execution after the exchange is completed.
Why Use Exchanger?
Sometimes two threads need to share data directly without using:
• Shared variables • Queues • Complex synchronization
Exchanger provides a simple and safe mechanism for such scenarios.
Example: Suppose one thread generates data and another thread processes it.
Producer Thread:
Creates a batch of records.
Consumer Thread:
Processes the previous batch.
Using Exchanger:
• Producer hands over the completed batch. • Consumer receives the batch instantly. • Both continue working efficiently.
Code Example:
import java.util.concurrent.Exchanger;
public class Demo {
public static void main(String[] args) {
Exchanger<String> exchanger =
new Exchanger<>();
Thread producer =
new Thread(() -> {
try {
String data =
"Data From Producer";
String response =
exchanger.exchange(data);
System.out.println(
"Producer Received: "
+ response);
} catch (InterruptedException e) {
Thread.currentThread()
.interrupt();
}
});
Thread consumer =
new Thread(() -> {
try {
String data =
"Data From Consumer";
String response =
exchanger.exchange(data);
System.out.println(
"Consumer Received: "
+ response);
} catch (InterruptedException e) {
Thread.currentThread()
.interrupt();
}
});
producer.start();
consumer.start();
}
}Possible Output:
Producer Received: Data From Consumer
Consumer Received: Data From Producer
What Happens Internally?
Step 1:
Thread A calls:
exchange(objectA)
Step 2:
Thread A waits.
Step 3:
Thread B calls:
exchange(objectB)
Step 4:
Objects are exchanged.
Step 5:
Both threads resume execution.
Blocking Behavior
The exchange() method is a blocking operation.
Example:
Thread A arrives first.
It waits until Thread B also calls exchange().
Only then does the exchange occur.
Timeout Version
To avoid waiting forever, Exchanger provides a timeout-based method.
Example:
exchange(data, 5, TimeUnit.SECONDS);
If no partner thread arrives within the specified time:
TimeoutException is thrown.
Common Use Cases
• Producer-Consumer systems • Data processing pipelines • Parallel algorithms • Buffer swapping • Thread coordination
Real-World Example
Imagine a file processing application.
Producer Thread:
Reads data from a file into Buffer A.
Consumer Thread:
Processes Buffer B.
After processing:
Buffers are exchanged.
This avoids creating new buffers repeatedly and improves performance.
Exchanger vs BlockingQueue
Exchanger:
• Two-way data exchange • Exactly two participating threads • Both threads send and receive data
BlockingQueue:
• One-way communication • Multiple producers and consumers • Data is inserted and removed
Interview Tip: A concise interview answer is:
"The Exchanger class is a synchronization utility that allows two threads to exchange objects at a common meeting point. Each thread provides an object using the exchange() method and receives the object supplied by the other thread. It is commonly used in producer-consumer scenarios and data processing pipelines where two threads need to swap data safely and efficiently."