learningJAVA
learningJAVA

Reputation: 11

Why notify() is not working in below code?

I want to print my odd even number in order 1 2 3 4 5 6. I think first notify call in odd-thread should unblock the even-thread wait() to print next even number but it is not the case. It is printing only "1"

class T1 extends Thread {
    private String[] s1;
    private boolean flag;

    public T1(String[] args, boolean flag) {
        this.flag = flag;
        this.s1 = args;
    }

    public synchronized void run() {
        for (int i = 0; i < s1.length; i++) {
            if(flag)
            {
                try {
                   wait();
                } catch (InterruptedException e) {
                   System.out.println("exception");
                }
            }
            System.out.println(s1[i]);
            notify();
            flag = true;
        }
    }
}

public class TestThread {
    public static void main(String[] args) {
        String[] s1 = { "1", "3", "5" };
        String[] s2 = { "2", "4", "6" };

        Runnable odd = new T1(s1,false);
        Runnable even = new T1(s2,true);

        new Thread(even,"even-thread ").start();
        new Thread(odd,"odd-thread ").start();

    }
}

Upvotes: 0

Views: 85

Answers (3)

Heng
Heng

Reputation: 96

You may need the code like this:

class MyThread extends Thread {
    private Object object;
    private String[] s1;

    public MyThread(String[] args, Object object) {
        this.object = object;
        this.s1 = args;
    }

    public void run() {
        synchronized (object) {
            for (int i = 0; i < s1.length; i++) {
                System.out.println(s1[i]);
                object.notifyAll();
                if (i == s1.length - 1) return;
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

public class TestThread {
    private static Object object = new Object();

    public static void main(String[] args) {
        String[] s1 = { "1", "3", "5" };
        String[] s2 = { "2", "4", "6" };
        Thread odd = new MyThread(s1, object);
        odd.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Thread even = new MyThread(s2, object);
        even.start();
    }
}

the output is:

1
2
3
4
5
6

Upvotes: 0

bowmore
bowmore

Reputation: 11280

As others point out, the two threads use different monitors, they should use a shared object as a monitor.

However, even fixing that will not solve all your problems. As it is I also see opportunity for a missed signal. (One thread may call notify, when the other isn't waiting).

All in all you don't regard some of the guidelines that should be used for wait-notify.

From Java Concurrency in Practice :

When using condition waits (Object.wait or Condition.await):

  • Always have a condition predicate—some test of object state that must hold before proceeding;
  • Always test the condition predicate before calling wait, and again after returning from wait;
  • Always call wait in a loop;
  • Ensure that the state variables making up the condition predicate are guarded by the lock associated with the condition queue;
  • Hold the lock associated with the the condition queue when calling wait, notify, or notifyAll; and
  • Do not release the lock after checking the condition predicate but before acting on it.

Upvotes: 3

Warren Dew
Warren Dew

Reputation: 8928

Your threads are notifying themselves rather than notifying the other thread.

You could fix this by notifying the other thread after synchronizing on its monitor. However, it would be better to wait() and notify() on a shared Object.

Upvotes: 2

Related Questions