arrow_backBack to Blog

Java Program to Print Odd/Even Numbers using 2 Threads

Printing odd and even numbers in sequence using 2 threads is a use case of synchronization and inter thread communication.
Java Program to Print Odd/Even Numbers using 2 Threads

Printing odd and even numbers in sequence using 2 threads is a use case of synchronization and inter thread communication.

Problem Statement

We have to print odd and even numbers in sequence using 2 threads, that means one thread is printing only odd numbers and another one is printing even numbers only.

Solution

Let’s say we have a common resource called Printer and 2 threads called OddPrinter and EvenPrinter are trying to access it. In order to make them print in sequence, we need to use below 2 concepts.

  • Resource synchronization: Whenever multiple threads are accessing a common resource, we need to synchronize that resource so that it can be accessed by 1 thread at a time and data discrepancy can be avoided.
  • Inter thread communication: Whenever we need communication between threads, we use this concept. In our example, to make them print in sequence, we need to make both the printers/threads communicate with each other. We achieve this by using wait(), notify() and notifyAll() methods in Java.

Implementation

To implement the solution, we need to break it down into 4 pieces which are the following.

  • CommonPrinter
  • OddPrinter
  • EvenPrinter
  • Main class to run the code

CommonPrinter

This class contains logic. The Printer object is the resource that gets accessed by both the threads hence it is synchronized.

It offers 2 methods i.e. printEven() and printOdd() that get called by EvenPrinter and OddPrinter threads respectively.

public class Printer {
    private final int max;

    public Printer(int max) {
        this.max = max;
    }

    public void printEven() throws InterruptedException {
        synchronized (this) {
            for (int i = 0; i < max; i++) {
                if (i % 2 == 0) {
                    System.out.println(Thread.currentThread().getName() + "-" + i);
                    notify();
                } else {
                    wait();
                }
            }
        }
    }

    public void printOdd() throws InterruptedException {
        synchronized (this) {
            for (int i = 0; i < max; i++) {
                if (i % 2 == 0) {
                    wait();
                } else {
                    System.out.println(Thread.currentThread().getName() + "-" + i);
                    notify();
                }
            }
        }
    }
} 

OddPrinter

OddPrinter is a Runnable task that gets executed via a Thread. We can also make OddPrinter a thread by extending the Thread class but for simplicity we have made it a Runnable task.

It internally calls the printOdd() of the Printer class.

public class OddPrinter implements Runnable {
    private final Printer printer;

    public OddPrinter(Printer printer) {
        this.printer = printer;
    }

    @Override
    public void run() {
        try {
            printer.printOdd();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

EvenPrinter

EvenPrinter is also a Runnable task that gets run by a Thread. It calls the printEven() of the Printer class to print even numbers.

public class EvenPrinter implements Runnable {
        private final Printer printer;

        public EvenPrinter(Printer printer) {
            this.printer = printer;
        }

        @Override
        public void run() {
            try {
                printer.printEven();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

Main Class

In the main class we create an object of the Printer class which is going to be used by OddPrinter and EvenPrinter

The Printer class takes a parameter called max that takes a number till what you want to print the numbers.

public class Main {
    public static void main(String[] args) {
        Printer printer = new Printer(10);
        Thread odd = new Thread(new OddPrinter(printer));   //Common printer to be used by OddPrinter  
        odd.setName("ODD");
        Thread even = new Thread(new EvenPrinter(printer)); //Common printer to be used by EvenPrinter 
        even.setName("EVEN");
        odd.start();
        even.start();
    }
}

Output

EVEN-0 ODD-1 EVEN-2 ODD-3 EVEN-4 ODD-5 EVEN-6 ODD-7 EVEN-8 ODD-9