程序停止:wait()和notify()

时间:2015-05-09 14:57:03

标签: java multithreading wait synchronized notify

我试图实现这个目的:创建两个不同的线程,一个打印奇数,一个打印偶数。一旦一个线程打印一个数字,它就必须等待另一个线程,依此类推,即一个接一个。

为实现这一点,我使用synchronized块以及wait()和notify()。

我正在创建一个类,其对象将用于传递给两个线程中的synchronized块。

以下是代码:

- >这是将被传递给synchronized块的used对象。

package com.vipin.multithread.variousdemos;

    public class SyncObject {

        public SyncObject () {  

        }
}

奇数线程:

package com.vipin.multithread.variousdemos;

public class OddThread implements Runnable {

private Thread t;
int index=0;
SyncObject so=null;

int odd_nums[] = {1,3,5,7,9};

public OddThread(SyncObject so) {
    t = new Thread(this,"Odd Thread");
    this.so = so;
    t.start();
}

public Thread getThreadInstance() {
    return t;
}

@Override
public void run() {
    while (true) {
        synchronized(so) {
            System.out.println("Odd num is --->" + odd_nums[index]);
            try {
                so.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            index++;
            so.notify();
            if(index>=5) {
                return;
            }
        }
    }
}
}

Even Thread:UPDATE

package com.vipin.multithread.variousdemos;

public class EvenThread implements Runnable {

private Thread t;
int index=0;
SyncObject so=null;

int even_nums[] = {2,4,6,8,10};

public EvenThread(SyncObject so) {
    t = new Thread(this, "Even thread");
    this.so = so;
    t.start();
}

public Thread getThreadInstance() {
    return t;
}

@Override
public void run() {
    while(true) {   
        synchronized(so) {
            System.out.println("Even num is --->" + even_nums[index]);
            so.notify(); <-- Here we are notifying.
            try {
                so.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            index++;
            //so.notify(); <-- commented out.
            if(index>=5) {
                break;
            }
        }
    }
}
}

主要应用:

package com.vipin.multithread.variousdemos;

public class EvenOddDemo {

public static void main(String[] args) throws InterruptedException {
    SyncObject so = new SyncObject();

    OddThread ot = new OddThread(so);
    EvenThread et = new EvenThread(so);

    System.out.println("\nIn main thread");

    Thread.sleep(1000000000);

    System.out.println("Exiting main thread...");
}
}

---&GT;如代码所示,我创建两个线程来打印偶数和奇数。我正在使用synchronized块,并传递类型==&gt;的对象SyncObject。

SyncObject我作为参数传递给main中的这些不同线程。

然而,这个程序停止了,即只停留第一个语句,然后它永远等待:

这是输出:

奇数是---> 1

在主线程中 偶数是---> 2

我无法理解为什么这个程序会等待,我正在使用我们正在调用synchronized(),wait()和notify()的SAME对象。根据我的理解,它应该工作,不知道为什么这不起作用。

关于为什么这是永远等待的任何线索。

更新:

我在代码中做了一些更改,UPDATE并且工作正常。

我还有一些疑问。即使没有锁定监视器,线程也会调用notify(),就像我更新代码后的情况一样。

事件顺序:

首先执行奇数线程,然后调用wait()&lt; - 它释放监视器,现在处于睡眠模式。

甚至线程运行,打印msg,并调用notify()&lt; - 这里我没有清楚的理解。

当Even调用notify()时,那时它有监视器,所以当它调用notify()时,是否仍然拥有监视器?

现在,在Even调用notify()之后,奇数线程得到通知,因此它从正在休眠的点开始执行。它正在做一些执行并调用notify(),在那一点上我认为奇数线程不拥有监视器,它调用notify()。所以,我的问题是,无论线程是否拥有监视器,notify()的工作方式是否相同?

只有当人们执行代码时,才能真正理解这一点。我读了书,我觉得我理解了一切,似乎我又回到了原点!

1 个答案:

答案 0 :(得分:2)

这里的问题只是两个线程直接进入等待状态。线程1获得so,打印值然后等待。线程2然后得到so,打印值然后等待。所以两个人都在睡觉,因为没有人在那里通知他们。因此,一个简单的解决方法就是在so.notify()之前进行so.wait()。然后他们没有无限期待。

修改

奇数线程开始,执行&amp;然后等待。然后甚至线程启动,执行,通知&amp;然后等待。甚至线程都会锁定监视器,直到它进入等待状态。

当偶数线程调用通知时,奇数线程唤醒&amp;民意调查锁定。一旦偶数线程进入等待(并释放锁定),则奇数线程可以获得锁定。

如果偶数线程没有调用notify,则奇数线程将继续休眠。偶数线程将等待&amp;释放了锁。没有线程轮询或尝试获取锁,因此程序保持挂起状态。

documentation也提供了类似的解释。我希望能够解除你的疑虑。