Java线程:等待并通知方法

sat*_*esh 3 java multithreading notify wait

我有一个调用该wait方法的线程,只有当notify从其他类调用该方法时才能唤醒:

 class ThreadA {
     public static void main(String [] args) {
         ThreadB b = new ThreadB();
         b.start();

         synchronized(b) {
             try {
                 System.out.println("Waiting for b to complete...");
                 b.wait();
             } catch (InterruptedException e) {}
             System.out.println("Total is: " + b.total);
         }
     }
 }

class ThreadB extends Thread {
    int total;
    public void run() {
        synchronized(this) {
            for(int i=0;i<100;i++) {
                total += i;
            }
            notify();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码synchronizedmain,如果块中,如果ThreadA不执行第一个而不是另一个同步块执行并完成,则ThreadA执行其synchronized块和调用wait,将要发生什么以及如何再次通知?

tem*_*def 10

如果之前ThreadB通过它的synchronizedThreadA,那么ThreadA将无限期地阻止调用wait.不会以某种方式通知其他线程已经完成.

问题是,你正在尝试使用wait,并notify在他们没有设计使用方式.通常,wait并且notify用于让一个线程等待直到某个条件为真,然后让另一个线程发出信号表明该条件可能已经变为真.例如,它们经常被用作如下:

/* Producer */
synchronized (obj) {
    /* Make resource available. */
    obj.notify();
}

/* Consumer */
synchronized (obj) {
    while (/* resource not available */)
        obj.wait();

    /* Consume the resource. */
}
Run Code Online (Sandbox Code Playgroud)

上面代码工作的原因是首先运行哪个线程并不重要.如果生产者线程创建了一个资源但没有人waitobj运行,那么当消费者运行时它将进入while循环,注意资源已经生成,然后跳过调用wait.然后它可以消耗资源.另一方面,如果消费者首先运行,它将在while循环中注意到资源尚不可用,并且将由wait某个其他对象通知它.然后,另一个线程可以运行,生成资源以及notify资源可用的使用者线程.一旦原始线程被唤醒,它将注意到循环的条件不再是真的并且将消耗该资源.

更一般地说,Java建议您总是wait在循环中调用,因为虚假通知中线程可以从调用中唤醒,wait而不会被通知任何内容.使用上述模式可以防止这种情况.

在您的特定实例中,如果您想确保ThreadBThreadA执行之前已经完成运行,您可能希望使用Thread.join(),它会显式阻塞调用线程,直到执行其他某个线程.更一般地说,您可能希望查看Java提供的一些其他同步原语,因为它们通常比wait和使用起来更容易notify.