Odd even number printing using thread

You're waiting and notifying different objects (monitors).

The idea is that you can call obj.wait() to wait for someone to do obj.notify(), while you're doing objA.wait() and objB.notify().

Change your printOdd method to something like

private void printOdd(int i) {
    synchronized (lock) {                        // <-------
        while (!oddTurn) {
            try {
                lock.wait();                     // <-------
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(type + i);
        oddTurn = false;
        lock.notifyAll();                        // <-------
    }
}

and the printEven method similarly.

Then provide the NumberPrinter with a lock object:

Object lock = new Object();
Thread odd = new Thread(new NumberPrinter("odd", lock));
Thread even = new Thread(new NumberPrinter("even", lock));

Output:

odd1
even2
odd3
even4
odd5
even6
odd7
even8
odd9

There are a lot of bugs in the code.

First of all, the synchronized statements have no effect whatsoever. You create two thread instances, and each calls only its own methods. synchronized is only useful if another thread can call a method.

Then notifyAll() has no effect for the same reasons. odd.notifyAll() doesn't reach even hanging in the wait().

So what you need is another object which contains the state and which both threads can see and use. Use synchronized, wait() and notifyAll() on that third instance.


The same can be solved using Lock interface:

NaturalOrder.java

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class NaturalOrder {

    public int currentNumber = 1;
    public boolean evenOdd = false;

    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    public static void main(String[] args) {
        NaturalOrder naturalOrder = new NaturalOrder();
        Thread t1 = new Thread(new OddNumberLock(naturalOrder, naturalOrder.lock, naturalOrder.condition));
        Thread t2 = new Thread(new EvenNumberLock(naturalOrder, naturalOrder.lock, naturalOrder.condition));
        t1.start();
        t2.start();
    }
}

OddNumberLock.java

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class OddNumberLock implements Runnable {

    NaturalOrder naturalOrder;
    Lock lock;
    Condition condition;

    public OddNumberLock(NaturalOrder naturalOrder, Lock lock, Condition condition) {
        this.naturalOrder = naturalOrder;
        this.lock = lock;
        this.condition = condition;
    }

    @Override
    public void run() {
        lock.lock();
        while (naturalOrder.currentNumber < 20) {
            while (naturalOrder.evenOdd != false) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            try {
                Thread.sleep(ThreadLocalRandom.current().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (naturalOrder.currentNumber % 2 != 0) {
                System.out.println(naturalOrder.currentNumber);
            }
            naturalOrder.currentNumber++;
            naturalOrder.evenOdd = true;

            condition.signalAll();
        }
        lock.unlock();
    }
}

EvenNumberLock.java

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class EvenNumberLock implements Runnable {

    NaturalOrder naturalOrder;
    Lock lock;
    Condition condition;

    public EvenNumberLock(NaturalOrder naturalOrder, Lock lock, Condition condition) {
        this.naturalOrder = naturalOrder;
        this.lock = lock;
        this.condition = condition;
    }

    @Override
    public void run() {
        lock.lock();
        while (naturalOrder.currentNumber < 20) {
            while (naturalOrder.evenOdd != true) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            try {
                Thread.sleep(ThreadLocalRandom.current().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (naturalOrder.currentNumber % 2 == 0) {
                System.out.println(naturalOrder.currentNumber);
            }
            naturalOrder.currentNumber++;
            naturalOrder.evenOdd = false;
            condition.signalAll();
        }
        lock.unlock();
    }
}