June 20, 2022

Print Odd And Even Numbers Using Two Threads in Java

In this post we’ll see how to print odd and even numbers using two threads in Java. This is an important Java multithreading interview question asked quite frequently.

Since two threads are used to alternatively print odd and even numbers so this program also shows how to synchronize threads and how inter thread communication works.

Printing odd and even numbers using two threads

You can use wait and notify methods to write a Java program to print odd and even numbers. See example.

you can also write the Java program using Semaphore which is a synchronization aid in java.util.concurrent package. See example.

Using wait() and notify() methods

In the Java program there are two Runnable tasks one for printing even numbers and another for printing odd numbers. Two threads are created to run these tasks and inter thread communication is done using wait notify.

There is also a class Printer with methods printEven() and printOdd(), instance of this class is shared between threads.

class PrintEvenTask implements Runnable{
  Printer printer;
  int max;
  PrintEvenTask(Printer printer, int max){
    this.printer = printer;
    this.max = max;
  }
  @Override
  public void run() {
    for(int i = 2; i <= max; i+=2){		
      printer.printEven(i);
    }   
  }
}

class PrintOddTask implements Runnable{
  Printer printer;
  int max;
  PrintOddTask(Printer printer, int max){
    this.printer = printer;
    this.max = max;
  }
  @Override
  public void run() {
    for(int i = 1; i <= max; i+=2){
      printer.printOdd(i);
    }   
  }
}

public class Printer {
  boolean evenFlag = false;
  //Prints even numbers 
  public void printEven(int num){
    synchronized (this) {
      while(!evenFlag){
        try {
          wait();
        } catch (InterruptedException e) {
          System.out.println("Thread Interrupted" + e.getMessage());
        }
      }
      System.out.println(Thread.currentThread().getName() + " - " + num);
      evenFlag = false;
      // notify thread waiting for this object's lock
      notify();
    }
  }
	
  //Prints odd numbers
  public void printOdd(int num){
    synchronized (this) {
      while(evenFlag){
        try {
          //make thread to wait
          wait();
        } catch (InterruptedException e) {
          System.out.println("Thread Interrupted" + e.getMessage());
        }
      }
      System.out.println(Thread.currentThread().getName() + " - " + num);
      evenFlag = true;
      // notify thread waiting for this object's lock
      notify();
    }
  }
  public static void main(String[] args) {
    Printer printer = new Printer();
    // creating two threads
    Thread t1 = new Thread(new PrintOddTask(printer, 10), "Odd");
    Thread t2 = new Thread(new PrintEvenTask(printer, 10), "Even");
    t1.start();
    t2.start();
  }
}
Output
Odd - 1
Even - 2
Odd - 3
Even - 4
Odd - 5
Even - 6
Odd - 7
Even - 8
Odd - 9
Even – 10

Once the threads are started and start executing run() method of their Runnable task, printEven() and printOdd() methods are called. There based on the boolean flag one of the thread goes into wait state and other prints the number and also notifies the other thread using notify() method.

Using Semaphores

Semaphore implementation provided in Java is a counting Semaphore where Semaphore is initialized with permits. Critical section can only be executed after acquiring a permit and it can be released after the execution. Thread is blocked until a permit is available.

For printing odd and even numbers using two threads two Semaphores are used, one initialized with a single permit and another with zero permit. Semaphore with one permit is used for printing odd number and another Semaphore is used for printing even numbers, since it has zero permits initially that ensures even number is not printed first.

class PrintEvenTask implements Runnable{
  Printer printer;
  int max;
  PrintEvenTask(Printer printer, int max){
    this.printer = printer;
    this.max = max;
  }
  @Override
  public void run() {
    for(int i = 2; i <= max; i+=2){		
      printer.printEven(i);
    }   
  }
}

class PrintOddTask implements Runnable{
  Printer printer;
  int max;
  PrintOddTask(Printer printer, int max){
    this.printer = printer;
    this.max = max;
  }
  @Override
  public void run() {
    for(int i = 1; i <= max; i+=2){
      printer.printOdd(i);
    }   
  }
}

public class Printer {
  boolean evenFlag = false;
  Semaphore semaphoreEven = new Semaphore(0);
  Semaphore semaphoreOdd = new Semaphore(1);
  //Prints even numbers 
  public void printEven(int num){			
    try {
      semaphoreEven.acquire();
    } catch (InterruptedException e) {
      System.out.println("Thread Interrupted" + e.getMessage());
    }		
    System.out. println(Thread.currentThread().getName() + " - " + num);
    semaphoreOdd.release();
  }
	
  //Prints odd numbers
  public void printOdd(int num){
    try {
      semaphoreOdd.acquire();
    } catch (InterruptedException e) {
      System.out.println("Thread Interrupted" + e.getMessage());
    }		
    System.out. println(Thread.currentThread().getName() + " - " + num);
    semaphoreEven.release();
  }
  public static void main(String[] args) {
    Printer printer = new Printer();
    // creating two threads
    Thread t1 = new Thread(new PrintOddTask(printer, 10), "Odd");
    Thread t2 = new Thread(new PrintEvenTask(printer, 10), "Even");
    t1.start();
    t2.start();
  }
}
Output
Odd - 1
Even - 2
Odd - 3
Even - 4
Odd - 5
Even - 6
Odd - 7
Even - 8
Odd - 9
Even - 10

Once the threads are started and execute run() method of their Runnable task printEven() and printOdd() methods are called. Since semaphoreOdd instance is initialized with one permit so it can acquire and run the code where as semaphoreEven instance has 0 permits so the other thread is blocked.

When semaphoreEven.release(); method is called from the printOdd() method that increments permit by 1 for semaphoreEven which can then be acquired in the printEven() method. Same way semaphoreOdd.release(); method is called in the printEven() method to release the already acquired permit of semaphoreOdd instance.

That's all for the topic Print Odd And Even Numbers Using Two Threads in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment