如何在 Java 中决定 wait() 的循环条件

how to decide the looping condition for wait() in Java

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

我很难理解我们必须在循环中给出的条件是什么。通常,我见过:

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

我很难理解在我们保持 wait() 的循环中使用的 "condition"。

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

由于这是线程间通信,我们需要同步,所以我很难确定我必须为这两个不同的线程在循环中保持 wait() 的条件是什么。

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

循环条件应该检查​​是否需要暂停执行(当前class的线程)

以著名的生产者-消费者问题为例,生产者在某种程度上看起来像

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

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

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

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!");

    }

}

您提到了两个 类 所以它们的同步方法不会相互同步。这就是我们在监视器上同步的原因,因为这两个对象必须共享一些东西才能使它们 "hear" 彼此。