Java Programs›Multithreading›Print Odd and Even Numbers Using Two Threads

Print Odd and Even Numbers Using Two Threads in Java

advanced·  Multithreading  ·  Concurrency

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.

Input
max = 10
Output
odd: 1, even: 2, odd: 3, ... even: 10

Java Program

Java
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

odd: 1 even: 2 odd: 3 even: 4 odd: 5 even: 6 odd: 7 even: 8 odd: 9 even: 10

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.

How It Works
  1. 1next holds the number to print, and its parity decides the turn.
  2. 2Inside the synchronized method, a thread calls wait() while the next number isn't its kind.
  3. 3After printing, it increments next and calls notifyAll() so the other thread re-checks the condition.
  4. 4A final notifyAll() lets the waiting thread see that the work is finished and exit.
Even if the even thread starts first, it finds 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

synchronizedwait()notifyAll()shared turn variable

Approach 2: Using Two Semaphores

Java
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

odd: 1 even: 2 odd: 3 even: 4 odd: 5 even: 6 odd: 7 even: 8 odd: 9 even: 10

Core Logic

Two semaphores act like a baton: each thread acquires its own before printing and releases the other's afterwards.

How It Works
  1. 1oddTurn starts with one permit, so the odd thread goes first; evenTurn starts with none.
  2. 2The odd thread acquires oddTurn, prints, then releases evenTurn.
  3. 3The even thread does the mirror image, so the threads strictly alternate.
After printing 1, the odd thread blocks on 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

Semaphoreacquire()release()baton passing

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.

Learn the Concept

Related Programs