How to use Exchanger in Java with Example
Hello guys, if you are working in a concurrent Java application then you might have heard about the Exchanger class of java.util.concurrent
package. The Exchanger in Java is another concurrency or synchronization utility introduced in Java 1.5 along with CountDownLatch, CyclicBarrier, and Semaphores. As the name suggests, the Exchanger
allows two Threads to meet and exchange data at the rendezvous or meeting point. The java.util.Exchanger
is a parametric class, which defines and holds the type of object to be exchanged. It has an overloaded method called theexchange()
, which is used to exchange objects between threads.
This is a blocking method, which means the Thread, which calls theexchange()
method wait at exchange point until another Thread arrives. Once another thread arrives, both exchange objects and return from this method. An overloaded version of the exchange method accepts additional
TimeUnit object and wait until time out.
By the way, you can also interrupt a Thread waiting at the exchange point for other participants. Unlike CountDownLatch
, CyclicBarrier
, or Semaphore
, the Exchanger
utility can only synchronize two threads, which makes it ideal for solving the classical producer-consumer problem.
In this Java Concurrency tutorial, you will learn how to use Exchanger in Java by implementing a producer-consumer design pattern using Exchanger. Btw, I am assuming that you are familiar with Java programming syntax and semantics, if you are a complete beginner to Java then you may find it difficult to understand this example.
Java Exchanger Example
The Exchanger
class is rather a simple synchronization utility to understand and use. In the last couple of concurrency tutorials, we have solved producer consumers using wait and notify (see here) and also implemented producer-consumer using BlockingQueue, now it’s time to use Exchanger to implement the same.
In this Java concurrency tutorial, we will be creating one producer and one consumer thread, which will exchange the buffer using the Exchanger utility class.
In general, here is how Exchanger works :
1. You first create an Exchange object like Exchanger<Deque<Long>> stringExchanger = new Exchanger<>()
; this defines what type of object will be exchanged between threads. In this case, two threads will exchange the Deque
object, containing long values.
2. When Thread A is ready to exchange its buffer or object, it calls the Exchanger.exchange()
method. This is a blocking method, and Thread A will be blocked until Thread B come and transfer its objects to Thread A or Thread A is interrupted or timeout.
3. When Thread B is ready, it also calls the exchange()
method. Now both Thread A and B exchange each other’s object and return from the exchange method.
4. Once the exchange completes, Thread A has Thread B’s object and vice-versa.
On the same note, I would like to emphasize the importance of Java concurrency skills and urge every Java developer to spend some time mastering Java concurrent classes.
Java Program with Exchanger in Concurrency
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import java.util.ArrayDeque; import java.util.Deque; import java.util.concurrent.Exchanger; /** * Exchanger Example in Java. Exchanger allows two Threads to meet at exchange * point and exchange data structure or objects. In this Java program, exchanger * is used to exchange buffer between producer and consumer. * @author Javin Paul */ public class JavaExchangerTutorail { public static void main(String args[]) throws InterruptedException { //Creating Exchanger to exchange String object with other thread final Exchanger> exchanger = new Exchanger>(); Thread producer = new Thread( "Producer : " ){ @Override public void run(){ Deque stack = new ArrayDeque(); //producer thread insert elments into stack while (stack.isEmpty()) { |
1 2 3 4 5 6 7 8 | stack.add(System.nanoTime()% 1000 ); //if stack is not empty then exchange it to consumer thread try { System.out.println(Thread.currentThread().getName() + " ready to exchange : " + stack); |
1 | <br> |
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | // Exchanger return other Thread's object stack = exchanger.exchange(stack); System.out.println(Thread.currentThread().getName() + " got : " + stack); } catch (InterruptedException ie) { ie.printStackTrace(); } } } }; Thread consumer = new Thread( "Consumer : " ){ @Override public void run(){ Deque stack = new ArrayDeque(); //consumer thread takes object from stack and prints do { //if stack is empty then exchange it to producer for refill try { System.out.println(Thread.currentThread().getName() + " ready to exchange : " + stack); stack = exchanger.exchange(stack); System.out.println(Thread.currentThread().getName() + " got : " + stack); stack.remove(); } catch (InterruptedException ie) { ie.printStackTrace(); } } while (stack.isEmpty()) ; } }; producer.start(); |
1 | <br> |
1 2 | //sleeping before starting consumer to give producer time to produce Thread.sleep( 1000 ); |
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | consumer.start(); } } Output: Producer : ready to exchange : [ 247 ] Consumer : ready to exchange : [] Producer : got : [] Consumer : got : [ 247 ] Producer : ready to exchange : [ 692 ] Consumer : ready to exchange : [] Consumer : got : [ 692 ] Consumer : ready to exchange : [] Producer : got : [] |
1 | <br> |
Explanation of Code and Output
If you look at the above example, all code is inside the main method. We have made the Exchanger
instance final because we are accessing them from Anonymous inner class, and only final local variables are accessible from the anonymous inner class.
Later, we created two threads, Producer and Consumer. The producer checks the queue and if it’s empty, it adds the last three digits of current nano time and calls the exchange() method.
Now, until the Consumer thread arrives at the exchange point, I mean until it calls the exchange() method, the Producer thread will be blocked.
Once a consumer arrives, both exchange each other’s stack and return from the exchange() method. At this time, the Producer has an empty stack of consumers and the consumer has a non-empty stack of Producer, I mean, they have each other’s object.
For understanding, which thread is exchanging which stack, we print the content of stack before and after an exchange on each thread. If you look at the output, it’s self-explanatory.
By the way, as with threads, you are not guaranteed to get the output in the same order. In the third iteration, you can see the consumer has an emptied stack and ready to exchange empty stack even before producer thread gets scheduled and return from the exchange method.
That’s all on How to use Exchanger in Java. The exchanger class is a nice and simple synchronization utility and perfect for coordinating two threads. Exchanger should be used to implement a producer-consumer pattern with one producer and one consumer. If you like to learn more about Java concurrency classes I suggest you check out the following resources:
Further Learning
Java Multithreading, Concurrency, and Performance Optimization
Java Concurrency in Practice – The Book
Applying Concurrency and Multi-threading to Common Java Patterns
Other Java Concurrency Articles you may like
- The 2020 Java Developer RoadMap (roadmap)
- What is happens-before in Java Concurrency? (answer)
- 10 Java Multithreading and Concurrency Best Practices (article)
- Top 50 Multithreading and Concurrency Questions in Java (questions)
- Top 5 Books to Master Concurrency in Java (books)
- 10 Free Java Courses for Beginners and Intermediate developers (courses)
- How to avoid deadlock in Java? (answer)
- Understanding the flow of data and code in Java program (answer)
- Is Java Concurrency in Practice still valid in 2020 (answer)
- Difference between CyclicBarrier and CountDownLatch in Java? (answer)
- 10 Tips to become a better Java Developer in 2020 (tips)
- How to do inter-thread communication in Java using wait-notify? (answer)
- Top 5 Courses to Learn Java Multithreading in-depth (courses)
Thanks for reading this article so far. If you like this Java Concurrency tutorial then please share it with your friends and colleagues. If you have any questions or feedback, then please drop a note.
P. S. – If you are new to Java world and want to learn core concepts along with Concurrency but looking for some free courses to start with then you can also check out this free Java Multithreading course on Udemy. It is a good free course to learn Java Concurrency as well.
Published on Java Code Geeks with permission by Javin Paul, partner at our JCG program. See the original article here: How to use Exchanger in Java with Example Opinions expressed by Java Code Geeks contributors are their own. |