Print Odd and Even Numbers Using Two Threads in Java
Problem
Thread coordination means making threads take turns: each one waits until a shared condition says it may go, then hands control to the other.
Use two threads to print the numbers 1 to 10 in order, with one thread printing only the odd numbers and the other only the even numbers.
Java Program
public class OddEvenTwoThreads {
private int next = 1;
private final int max = 10;
synchronized void print(boolean wantOdd) throws InterruptedException {
while (next <= max) {
while (next <= max && (next % 2 == 1) != wantOdd) {
wait(); // not my turn yet
}
if (next > max) break;
System.out.println(Thread.currentThread().getName() + ": " + next);
next++;
notifyAll(); // hand the turn to the other thread
}
notifyAll(); // make sure the other thread can see we're finished
}
public static void main(String[] args) throws InterruptedException {
OddEvenTwoThreads printer = new OddEvenTwoThreads();
Thread odd = new Thread(() -> run(printer, true), "odd");
Thread even = new Thread(() -> run(printer, false), "even");
even.start(); // starting "even" first doesn't matter: it waits for 1 to be printed
odd.start();
odd.join();
even.join();
}
static void run(OddEvenTwoThreads p, boolean odd) {
try {
p.print(odd);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}Output
Core Logic
A shared counter decides whose turn it is: each thread waits while the next number belongs to the other thread, prints when it's its turn, and wakes the other one.
- 1
nextholds the number to print, and its parity decides the turn. - 2Inside the
synchronizedmethod, a thread callswait()while the next number isn't its kind. - 3After printing, it increments
nextand callsnotifyAll()so the other thread re-checks the condition. - 4A final
notifyAll()lets the waiting thread see that the work is finished and exit.
next = 1 is odd and waits until the odd thread prints 1.Key Point: The wait() sits inside a while loop, not an if, so a thread that wakes up re-checks whose turn it is before printing.
Key Concepts
Approach 2: Using Two Semaphores
import java.util.concurrent.Semaphore;
public class OddEvenSemaphores {
public static void main(String[] args) throws InterruptedException {
Semaphore oddTurn = new Semaphore(1); // odd goes first
Semaphore evenTurn = new Semaphore(0);
int max = 10;
Thread odd = new Thread(() -> {
try {
for (int i = 1; i <= max; i += 2) {
oddTurn.acquire();
System.out.println("odd: " + i);
evenTurn.release(); // pass the baton
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
Thread even = new Thread(() -> {
try {
for (int i = 2; i <= max; i += 2) {
evenTurn.acquire();
System.out.println("even: " + i);
oddTurn.release();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
odd.start();
even.start();
odd.join();
even.join();
}
}
Output
Core Logic
Two semaphores act like a baton: each thread acquires its own before printing and releases the other's afterwards.
- 1
oddTurnstarts with one permit, so the odd thread goes first;evenTurnstarts with none. - 2The odd thread acquires
oddTurn, prints, then releasesevenTurn. - 3The even thread does the mirror image, so the threads strictly alternate.
oddTurn until the even thread prints 2 and releases it.Key Point: Semaphores avoid explicit wait/notify and shared counters, which makes the alternation easier to read and to extend to three threads.
Key Concepts
Interview Questions
Why use notifyAll instead of notify here?
With notify, the single thread woken might be the wrong one, and if it just waits again the program can stall. notifyAll wakes everyone, and each thread re-checks the condition.
How would you extend this to three threads printing 1, 2, 3 in turn?
Use next % 3 to decide the turn, or three semaphores where each thread releases the next one in the cycle.