Today, we will see how to print odd even numbers using Blocking Queue.
We want to print odd even numbers using two different threads and so it will obviously require some kind of thread synchronization to communicate while one thread is printing the number. So one thread will become producer (odd) and other one (even) will become consumer. Java provides BlockingQueue for thread synchronization in these kind of scenarios.
BlockingQueue provides functions to support operations that awaits for the queue to become non-empty while retrieving elements or wait for the space to become available while inserting the elements.
In our example, we will use LinkedBlockingQueue which uses ReentrantLock (refer my earlier post) internally for thread synchronization. To implement the solution for our odd even thread, we will need two classes: TakeAndOfferNext class which is callable thread and OddAndEvenSignalling which will invoke the thread.
TakeAndOfferNext:
Now let's see the implementation of TakeAndOfferNext. We will need two blocking queues here: one for odd numbers and another one for even numbers.
BlockingQueue takeFrom;
BlockingQueue offerTo;
Blocking queue offers two synchronous operations called take() and offer(e). Take removes the element from the queue if it's non-empty and offer inserts to the queue if it's not full. Here, you dont' need to be aware of thread synchronization as blocking queue will take care of it through these two methods. So let's print odd even numbers using these blocking queues:
public void print() {
while (true) {
try {
int i = takeFrom.take(); //removes the value in the "from" queue
System.out.println(Thread.currentThread().getName() + " --> " + i);
offerTo.offer(i + 1); //increments the value by 1 and puts it in the "to" queue.
if (i >= (maxNumber - 1)) {
System.exit(0);
}
} catch (InterruptedException e) {
throw new IllegalStateException("Unexpected interrupt", e);
}
}
}
As you can see here we are looping through the continuous loop until it reaches the max number. In the loop, we first take the first number (odd one) from the first queue and pass the next number (even one) to the another queue.
Okay, half work is done now how do we take even element from the another queue which we set at the end ? Well, we will need two threads to do this job which will switch the odde and even queues alternately in below class.
OddAndEvenSignalling:
BlockingQueue odds = new LinkedBlockingQueue();
BlockingQueue evens = new LinkedBlockingQueue();
ExecutorService executorService = Executors.newFixedThreadPool(2);
Now, our two threads are ready to print odd and even numbers. So, let's pass it on to the TakeAndOfferNext class in such a way that it will switch odd and even queues in the print() method.
executorService.submit(new TakeAndOfferNext(odds, evens, MAX_NUMBER));
executorService.submit(new TakeAndOfferNext(evens, odds, MAX_NUMBER));
And that's it, your job is done !!!
Working code samples can be found here.
You can try producer consumer example using blocking queue as an exercise.
We want to print odd even numbers using two different threads and so it will obviously require some kind of thread synchronization to communicate while one thread is printing the number. So one thread will become producer (odd) and other one (even) will become consumer. Java provides BlockingQueue for thread synchronization in these kind of scenarios.
BlockingQueue provides functions to support operations that awaits for the queue to become non-empty while retrieving elements or wait for the space to become available while inserting the elements.
In our example, we will use LinkedBlockingQueue which uses ReentrantLock (refer my earlier post) internally for thread synchronization. To implement the solution for our odd even thread, we will need two classes: TakeAndOfferNext class which is callable thread and OddAndEvenSignalling which will invoke the thread.
TakeAndOfferNext:
Now let's see the implementation of TakeAndOfferNext. We will need two blocking queues here: one for odd numbers and another one for even numbers.
BlockingQueue takeFrom;
BlockingQueue offerTo;
Blocking queue offers two synchronous operations called take() and offer(e). Take removes the element from the queue if it's non-empty and offer inserts to the queue if it's not full. Here, you dont' need to be aware of thread synchronization as blocking queue will take care of it through these two methods. So let's print odd even numbers using these blocking queues:
public void print() {
while (true) {
try {
int i = takeFrom.take(); //removes the value in the "from" queue
System.out.println(Thread.currentThread().getName() + " --> " + i);
offerTo.offer(i + 1); //increments the value by 1 and puts it in the "to" queue.
if (i >= (maxNumber - 1)) {
System.exit(0);
}
} catch (InterruptedException e) {
throw new IllegalStateException("Unexpected interrupt", e);
}
}
}
As you can see here we are looping through the continuous loop until it reaches the max number. In the loop, we first take the first number (odd one) from the first queue and pass the next number (even one) to the another queue.
Okay, half work is done now how do we take even element from the another queue which we set at the end ? Well, we will need two threads to do this job which will switch the odde and even queues alternately in below class.
OddAndEvenSignalling:
BlockingQueue
BlockingQueue
ExecutorService executorService = Executors.newFixedThreadPool(2);
Now, our two threads are ready to print odd and even numbers. So, let's pass it on to the TakeAndOfferNext class in such a way that it will switch odd and even queues in the print() method.
executorService.submit(new TakeAndOfferNext(odds, evens, MAX_NUMBER));
executorService.submit(new TakeAndOfferNext(evens, odds, MAX_NUMBER));
And that's it, your job is done !!!
Working code samples can be found here.
You can try producer consumer example using blocking queue as an exercise.