-2

I want to develop an application that contains two threads thread1 and thread2. Thread 1 has to print even numbers upto 50 and thread 2 has to print odd numbers upto 50. And both threads should communicate such that the printing oreder should be 1,2, 50. I tried the following code. How to communicate between EvenThread and OddThread

public class TestPrint{
    public static void main(String[] args) {
        EvenThread et=new EvenThread();
        OddThread ot=new OddThread();
        et.start();
        ot.start();
    }
}

class EvenThread extends Thread{
    int even=0;
    @Override
    public void run() {
        synchronized(this){
            while(even<50){
                System.out.println(even);
                even=even+2;
                try {
                    this.wait();
                    notify();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

class OddThread extends Thread{
    int odd=1;
    @Override
    public void run() {
        synchronized(this){
            while(odd<50){
                System.out.println(odd);
                odd=odd+2;
                try {
                    this.wait();
                    notify();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • Why would you execute them concurrently if you need it to go in sequential order? –  Aug 04 '14 at 18:45

1 Answers1

1

Your threads need to use the same lock. In your code each of your two threads has its own lock, because the two threads are separate objects that are each using synchronized(this). That means they don't wait to take turns and they don't get notified when a thread calls notify or notifyAll (because only threads waiting on the same lock received the notification).

Add a lock object to your TestPrint class like this:

public static final Object LOCK = new Object();

and have your threads use that as their lock by changing their synchronized blocks to

synchronized(LOCK) {

Also the way you're calling notify right after calling wait doesn't make sense. You need to use notify after having written an entry, and wait while you're waiting to get an opportunity to write. You need to have some flag (for instance a volatile variable in the TestPrint class) that the threads use to decide when they can act, it's not safe to rely solely on notifications when figuring out when to act (because a thread can return from wait without having been notified).

Say you added another field to TestPrint, to hold the next value to be printed:

public static int nextValue = 1;

then the OddThread could have code like:

try {
    synchronized(TestPrint.LOCK) {
        // wait for nextValue to become odd
        while (TestPrint.nextValue % 2 == 0) {
            TestPrint.LOCK.wait();
        }
        // at this point oddthread has the lock,
        // and nextValue is odd
        System.out.println(TestPrint.nextValue);
        TestPrint.nextValue += 1;
        // tell the other thread it can proceed
        TestPrint.LOCK.notify();
    }
} catch (InterruptedException e) {
    // won't happen (no one is calling interrupt
    // on this thread)
}

See the section of the Oracle tutorial that discusses guarded blocks for examples of using wait and notify.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276