如何在Java

时间:2015-05-10 19:18:25

标签: java multithreading wait notify

我在Java中了解了多线程的wait(),并且根据文档,wait()应该始终处于循环中。

我很难理解我们必须在循环中给出的条件是什么。通常情况下,我看到了:

synchornized(obj) {
    while(some_condition) {
         obj.wait();
    }
    // some other code
}

我很难理解在我们保持wait()的循环中使用的“条件”。

我试图实现一个场景,我创建了两个不同的线程(实现Runnable接口的两个不同的类),用于打印奇数和偶数,如:1,2,3,4,5,6 ......

由于这是线程间通信而且我们需要同步,因此我很难将这两个不同线程的循环保持wait()的条件联系起来。

关于如何破译这一点(我们保持循环的条件)的任何线索都非常感激。

2 个答案:

答案 0 :(得分:1)

循环条件应检查是否需要临时暂停执行(当前类的线程)。

举一个着名的生产者 - 消费者问题的例子,生产者在某种程度上看起来像

synchronized(mySharedObj)
{
while(mySharedObj.length==maxSize)
{
 mySharedObj.wait();
}
}

如果 mySharedObj 上有n个生产者线程,则当共享资源(mySharedObj)达到其限制时,所有人都将等待。

答案 1 :(得分:1)

在这里,也许这几行会推动你朝着正确的方向前进,作为我之前评论的后续行动。

class LastPrintedMonitor {
    public boolean wasLastEven = false;

}

class PrinterOdd implements Runnable {

    LastPrintedMonitor monitor;

    public PrinterOdd(LastPrintedMonitor monitor) {
        this.monitor = monitor;
    }

    @Override
    public void run() {
        for (int i = 2; i < 40; i += 2) {
            synchronized (monitor) {
                while (!monitor.wasLastEven) {
                    try {
                        monitor.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                System.out.println(i);
                monitor.wasLastEven = false;
                monitor.notifyAll();
            }
        }

    }

}

class PrinterEven implements Runnable {

    LastPrintedMonitor monitor;

    public PrinterEven(LastPrintedMonitor monitor) {
        this.monitor = monitor;
    }

    @Override
    public void run() {
        for (int i = 1; i < 40; i += 2) {
            synchronized (monitor) {
                while (monitor.wasLastEven) {
                    try {
                        monitor.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                System.out.println(i);
                monitor.wasLastEven = true;
                monitor.notifyAll();
            }
        }

    }

}

public class EvenOddPrinterDemo {

    public static void main(String[] args) {
        LastPrintedMonitor monitor = new LastPrintedMonitor();

        Thread odd = new Thread(new PrinterOdd(monitor));
        Thread even = new Thread(new PrinterEven(monitor));

        odd.start();
        even.start();

        try {
            odd.join();
            even.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Done!");

    }

}

您提到了两个类,因此它们的同步方法不会彼此同步。这就是我们为什么要在显示器上进行同步的原因,因为必须有这两个对象共享的内容才能使它们听到&#34;听到&#34;彼此。