Java线程:等待并通知方法 [英] Java threads: wait and notify methods

查看:110
本文介绍了Java线程:等待并通知方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个调用 wait 方法的线程,并且只能在从某些方法调用 notify 方法时唤醒其他类:

I have a thread that calls the wait method and can only be awoken when the notify method called from some other class:

 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();
        }
    }
}

在上面的代码中,如果如果 ThreadA 未执行,同步阻止 main 首先,而是另一个同步块执行并完成,然后 ThreadA 执行其 synchronized 块并调用等待,将会发生什么以及如何再次通知?

In the above code if the synchronized block in main, if the ThreadA does not execute first and instead the other synchronization block executing and completes to completion, then ThreadA executes its synchronized block and calls wait, what is going to happen and how it will be notified again?

推荐答案

如果 ThreadB ThreadA 之前通过其 synchronized 块,然后 ThreadA 将无限期地阻止对 wait 的调用。它不会以某种方式通知其他线程已经完成。

If ThreadB gets through its synchronized block before ThreadA does, then ThreadA will block indefinitely on the call to wait. It won't somehow be notified that the other thread has already completed.

问题是你正在尝试使用等待以不被设计使用的方式通知。通常,等待 notify 用于让一个线程等待,直到某些条件为真,然后再生成另一个线程表明情况可能已成为现实。例如,它们通常按如下方式使用:

The problem is that you're trying to use wait and notify in ways that they are not designed to be used. Usually, wait and notify are used to have one thread wait until some condition is true, and then to have another thread signal that the condition may have become true. For example, they're often used as follows:

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

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

    /* Consume the resource. */
}

上述代码的作用原因是无关紧要哪个线程首先运行。如果生产者线程创建了一个资源而没有人等待> obj ,那么当消费者运行时它将进入 while 循环,注意资源已经生成,然后跳过调用 wait 。然后它可以消耗资源。另一方面,如果消费者首先运行,它会在中注意到循环该资源尚未可用且将等待用于通知它的其他一些对象。然后,另一个线程可以运行,生成资源,并且通知该资源可用的使用者线程。一旦原始线程被唤醒,它将注意到循环的条件不再是真的并将消耗资源。

The reason that the above code works is that it doesn't matter which thread runs first. If the producer thread creates a resource and no one is waiting on obj, then when the consumer runs it will enter the while loop, notice that the resource has been produced, and then skip the call to wait. It can then consume the resource. If, on the other hand, the consumer runs first, it will notice in the while loop that the resource is not yet available and will wait for some other object to notify it. The other thread can then run, produce the resource, and notify the consumer thread that the resource is available. Once the original thread is awoken, it will notice that the condition of the loop is no longer true and will consume the resource.

更一般地说,Java建议你总是打电话在循环中等待因为虚假通知,其中一个线程可以从调用等待没有得到任何通知。使用上述模式可以防止这种情况。

More generally, Java suggests that you always call wait in a loop because of spurious notifications in which a thread can wake up from a call to wait without ever being notified of anything. Using the above pattern can prevent this.

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

In your particular instance, if you want to ensure that ThreadB has finished running before ThreadA executes, you may want to use Thread.join(), which explicitly blocks the calling thread until some other thread executes. More generally, you may want to look into some of the other synchronization primitives provided by Java, as they often are much easier to use than wait and notify.

这篇关于Java线程:等待并通知方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆