Core Java multi-thread coding -- printing odd and even numbers with two threads and a blocking queue
Core Java Coding Questions and Answers for beginner to intermediate level
Q1 | Q2 | Q3 | Q4 | Q5 | Q6 |
This is an alternative approach using a blocking queue compared to using an AtomicInteger and a lock.
Q. Can you write code to print odd and even numbers by two threads in sequence?
A. Even though this is not a practical question, a handy beginner level question test your ability to write multi-threaded code.
Considerations:
Use a blocking queue: A BlockingQueue is used to have one thread produce objects, which another thread consumes.T he producing thread will keep producing new objects and insert them into the queue, until the queue reaches some upper bound on what it can contain. If the blocking queue reaches its upper limit, the producing thread is blocked while trying to insert the new object. The consuming thread keeps taking objects out of the blocking queue, and processes them. If the consuming thread tries to take an object out of an empty queue, the consuming thread is blocked until a producing thread puts an object into the queue.
You can use 2 blocking queues -- one for odd numbers and another for the even numbers.
Step: 1: Put 1 into the odd queue.
Step 2: The odd number thread
- takes the number out of the odd number queue
- prints the odd number
- increments the number by 1
- puts the even number in the even number queue.
- when the queue is empty, it is blocked.
Step 3: Similarly, The even number thread
- takes the number out of the even number queue
- prints the even number
- increments the number by 1
- puts the odd number in the even number queue.
- when the queue is empty, it is blocked.
Here is the diagram that depicts this.
Finally, here is the working code.
Step 1: The main class OddAndEvenSignalling.
import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; public class OddAndEvenSignalling { private static final int MAX_NUMBER = 10; public static void main(String[] args) { BlockingQueue<Integer> odds = new LinkedBlockingQueue<Integer>(); BlockingQueue<Integer> evens = new LinkedBlockingQueue<Integer>(); ExecutorService executorService = Executors.newFixedThreadPool(2); //odd numbers are removed from the "from" queue --> printed --> incremented --> placed on the "to" queue by one thread //"from" queue is "odd number" queue and "to" queue is "even number" queue executorService.submit(new TakeAndOfferNext(odds, evens, MAX_NUMBER)); //even numbers are removed from the "from" queue --> printed --> incremented --> placed on the "to" queue by another thread //"from" queue is "even number" queue and "to" queue is "odd number" queue executorService.submit(new TakeAndOfferNext(evens, odds, MAX_NUMBER)); odds.offer(1); } }
Step 2: The callable class TakeAndOfferNext that executes the logic as depicted in the diagram.
import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; public class TakeAndOfferNext implements Callable<Object> { BlockingQueue<Integer> takeFrom; BlockingQueue<Integer> offerTo; int maxNumber; public TakeAndOfferNext(BlockingQueue<Integer> takeFrom, BlockingQueue<Integer> offerTo, int maxNumber) { this.takeFrom = takeFrom; this.offerTo = offerTo; this.maxNumber = maxNumber; } public Object call() throws Exception { print(); return null; } 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); } } } }
Step 3: The output
pool-1-thread-2 --> 1 pool-1-thread-1 --> 2 pool-1-thread-2 --> 3 pool-1-thread-1 --> 4 pool-1-thread-2 --> 5 pool-1-thread-1 --> 6 pool-1-thread-2 --> 7 pool-1-thread-1 --> 8 pool-1-thread-2 --> 9 pool-1-thread-1 --> 10
Labels: Coding, Multi-threading
5 Comments:
excellent example. got good understanding about usage of blocking queue
Hi Arul, I want to print sequence of integers with two threads say upto 10. First I want Thread A to print 1 then thread B to print 1 something like below
pool-1-thread-2 --> 1
pool-1-thread-1 --> 1
pool-1-thread-2 --> 2
pool-1-thread-1 --> 2
pool-1-thread-2 --> 3
pool-1-thread-1 --> 3
pool-1-thread-2 --> 4
pool-1-thread-1 --> 4
pool-1-thread-2 --> 5
pool-1-thread-1 --> 5
...... with a pause of 1 sec
Hi Arul,
I suggest to use explicit lock with a condition queue where threads will co-operate by signal.
Any benefits over intrinsic locks?
it can also be implemented using SynchronousQueue.
Post a Comment
Subscribe to Post Comments [Atom]
<< Home