[Problem] Printing Even and Odd using Two Threads with Coordination

Problem

Create two threads - one that prints odd numbers till 10 in the format "Odd 1", "Odd 3" etc. and one that prints even numbers till 10 in the format "Even 0", "Even 2" etc..

Need to implement coordination between them so that the output will be:

Even0

Odd1

Even2

Odd3

Even4

Odd5

Even6

Odd7

Even8

Odd9

Even10

Hint: The order should be same theoretically and practically. Putting a sleep while printing might work in some cases, but it cannot be guaranteed always.

 

Solution

package com.javajee.threads;

enum CurrentState {
  EVEN, ODD
};

public class EvenOddSynchronization {

  public static volatile CurrentState currentState = CurrentState.EVEN;
  public static volatile Object lockObject = new Object();

  public static void main(String[] args) throws InterruptedException {

    Thread t1 = new Thread(new MyRunnableEven());
    Thread t2 = new Thread(new MyRunnableOdd());
    t1.start();
    t2.start();
  }
}

class MyRunnableEven implements Runnable {

  CurrentState allowedState = CurrentState.EVEN;

  @Override
  public void run() {

    for (int i = 0; i <= 10; i = i + 2) {
      synchronized (EvenOddSynchronization.lockObject) {
        while (allowedState != EvenOddSynchronization.currentState) {

          try {
            EvenOddSynchronization.lockObject.wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }

        System.out.println("Even: " + i);
        EvenOddSynchronization.currentState = CurrentState.ODD;
        EvenOddSynchronization.lockObject.notify();
      }
    }
  }
}

class MyRunnableOdd implements Runnable {

  CurrentState allowedState = CurrentState.ODD;

  @Override
  public void run() {

    for (int i = 1; i < 10; i = i + 2) {
      synchronized (EvenOddSynchronization.lockObject) {
        while (allowedState != EvenOddSynchronization.currentState) {

          try {
            EvenOddSynchronization.lockObject.wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }

        System.out.println("Odd: " + i);
        EvenOddSynchronization.currentState = CurrentState.EVEN;
        EvenOddSynchronization.lockObject.notify();
      }
    }
  }
}

Important Note

  • The currentState enum variable determines which thread should be executed. 

    • Each thread is assigned an allowed state

    • If the allowed state is different from current state, it will wait.

    • If the allowed state is same as current state, it will print number, change the state and notify the other waiting thread.

  • You may also use notifyAll instead of notify when you are using wait-loop-idiom, as suggested by the book Effective Java.

 

Alternate thoughts

  1. You might think to use a Thread.sleep to try to simulate the situation, but the behaviour can never be guaranteed always in that way.

  2. You may be tempted to use notify and wait without the wait-loop check as in  javaquizzes/question-53. Check the question for issues with this approach.

  3. You may be tempted to use wait and notify in different orders to solve above issue as in javaquizzes/question-54. Check the question for issues with this approach.

Search the Web

Custom Search

Searches whole web. Use the search in the right sidebar to search only within javajee.com!!!