Tuesday, November 11, 2014

Printing odd, even number alternately using two threads in Java.

This is my first post and I am going to start with a multi-threading problem in Java. The problem statement is there are two threads, lets name them EvenThread & OddThread. By using these two threads print an output such that first OddThread prints odd number and after that EvenThread prints even number and again OddThread prints odd number and so on. For example sample output

OddThread prints 1
EvenThread prints 2
OddThread print 3
and so on.


Both threads should operate upon common int variable to print even & odd output. I am going to post  solution that uses Java synchronized block,  wait() and notify() method to achieve result such that both threads prints odd even number alternately. Explanation is given below.

Java code:
class Main {
      
    public static void main(String[] args) {
        Counter counter = new Counter();//it will be used for locking.
        new Thread(new EvenTask(counter), "Even Thread").start();
        new Thread(new OddTask(counter), "Odd Thread").start();
    }
}

class Counter{
    //The int variable that is used by both threads.
    public int count = 1;
}

class EvenTask implements Runnable{
    private Counter counter;
  
    public EvenTask(Counter counter){
        this.counter = counter;
    }
  
    @Override
    public void run() {
        while (true) {
            synchronized (counter) {
                //If counter.num is odd then even thread will release lock and goes to wait state
                //so that odd thread can print.
                if(counter.count % 2!=0){
                    try {
                        counter.notify();
                        counter.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //Control will come here if odd thread has released lock
                //or if number is even.
                System.out.println(Thread.currentThread().getName()+"-"+counter.count);
                counter.count++;
                try {
                    Thread.sleep(200);//Some ms of sleep so that output is not very fast.
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

class OddTask implements Runnable{
    private Counter counter;
  
    public OddTask(Counter counter){
        this.counter = counter;
    }
  
    @Override
    public void run() {

        while (true) {
            synchronized (counter) {
                //If counter.num is even then odd thread will release lock and goes to wait state
                //so that even thread can print.
                if(counter.count % 2==0){
                    try {
                        counter.notify();
                        counter.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //Control will come here if even thread has released lock
                //or if number is odd.
                System.out.println(Thread.currentThread().getName()+"-"+counter.count);
                counter.count++;
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

In main method while creating EvenTask and OddTask runnable, object of Counter class is passed to constructor of both classes. This shared counter object is used for locking and also it has int variable count that is shared between both threads for printing odd/even number. Counter class int variable count is initialized to 1.

Inside run method of EvenTask there is if condition that check if count has odd value. If count has odd value then notify() is called which wakes up OddThread and after that wait(); is called which makes current thread i.e. EvenThread goes to waiting state. After OddThread wakes up it acquire lock (which is released by EvenThread) and print odd number and after that increment of count when next time if condition run count is even and code inside if condition of OddTask run and notify() and wait methods are called and this process keeps on repeating.
//if condition code from EvenTask
                if(counter.num % 2!=0){
                    try {
                        counter.notify();
                        counter.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

Similarly in OddTask we check if count has even value then waiting thread is notified and current thread (i.e. OddThread) goes to waiting state. If count is odd inside OddTask then code inside if condition does not run and odd number is printed.

I did not make Counter class instance variable count volatile because count variable read/write happens in synchronized context of both two threads and variable is not modified else where.
Since there are only two threads involved I have used notify() instead of notifyAll().

2 comments:

  1. Wonderful Explanation. Was very useful.

    ReplyDelete
  2. Hi The code is working fine when I ran its going infinite loop its not getting stopped Can you make changes to print only 20 numbers like upto 20 numbers I need even and odd numbers like that

    ReplyDelete