Printing numbers in sequence from alternating threads
This article demonstrates printing numbers in sequence from alternating threads. This is a very popular multi-threading question asked in Java technical interviews.
The Problem Statement
Print the natural sequence of integers starting from 1 from a set of 3 (or more) threads that take turns in a round robin fashion; such that, thread 1 prints 1, thread 2 prints 2, thread 3 prints 3 and then thread 1 prints 4 and so on.
The Solution
I have seen people writing crazy and complex logic to switch between threads. In this article, we present a more subtle and elegant way to achieve the objective.
First, we define a worker holding a blocking queue. The workers waits on the queue until it receives a number in it. It prints the number it receives, increments it and passes it on to the next worker in the chain.
Then, we create the required number of workers instances and tie them together to create a circular chain. Then, assign each worker a separate thread and set them off.
Each worker waits until it receives a number and then prints the number, increments it and passes the number to next worker in the chain. The next worker repeats the process and so on. As a result, the numbers are printed sequentially from different threads in the chain.
The Worker
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
class Worker implements Runnable{ BlockingQueue<Integer> q = new LinkedBlockingQueue<Integer>(); Worker next = null; // next worker in the chain public void setNext(Worker t) { this.next = t; } public void accept(int i) { q.add(i); } @Override public void run() { while (true){ try { int i = q.take(); // blocks till it receives a number System.out.println( Thread.currentThread().getName() + i); Thread.sleep(1000); // delay to slow the printing if (next != null){ next.accept(i+1); // pass the next number to the next worker } } catch (InterruptedException e) { System.err.println( Thread.currentThread().getName() + " interrrupted."); } } } } |
The Main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class SequencePrinter { public static void main(String[] args) { // Create the workers Worker w1 = new Worker(); Worker w2 = new Worker(); Worker w3 = new Worker(); // chain them in a round robin fashion w1.setNext(w2); w2.setNext(w3); w3.setNext(w1); // Create named threads for the workers Thread t1 = new Thread(w1, "Thread-1 - "); Thread t2 = new Thread(w2, "Thread-2 - "); Thread t3 = new Thread(w3, "Thread-3 - "); // start the threads t1.start(); t2.start(); t3.start(); // Seed the first worker w1.accept(1); } } |
The Output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Thread-1 - 1 Thread-2 - 2 Thread-3 - 3 Thread-1 - 4 Thread-2 - 5 Thread-3 - 6 Thread-1 - 7 Thread-2 - 8 Thread-3 - 9 Thread-1 - 10 Thread-2 - 11 Thread-3 - 12 .. .. |
A very nice approach.