使用等待通知示例在Java中进行线程间通信

Java中的等待和通知方法用于进行线程间通信,即如果一个线程想要告诉其他线程,它使用java.lang.Object的notify()和notifyAll()方法。等待和通知方法的经典示例是生产者消费者设计模式,其中一个线程产生并将某些东西放在共享存储桶中,然后告诉其他线程有一个对共享对象感兴趣的项目,消费者线程比选择项目更多没有wait()和notify(),消费者线程需要忙于检查,即使共享对象的状态没有变化。

这带来了一个关于使用wait和notify机制的有趣的观点,当发生线程改变共享对象的状态时,发生notify()的调用,即在这种情况下,生产者将桶从空变为空,并且消费者从非空变为空。

同样的等待和通知方法必须从同步上下文中调用,想知道为什么,请阅读此链接出于某种原因,这是有道理的。调用它们时要牢记的另一件重要事情是,使用循环来检查条件而不是如果块。

这对于初学者来说非常棘手,通常不了解差别,奇怪为什么wait和notify会被称为form循环。Joshua Bloch在他的书中有一个非常丰富的内容有效的Java,我强烈建议阅读。

简而言之,等待线程可能会醒来,而不会因虚假唤醒而改变其等待状态。

例如,如果由于共享队列为空而等待的消费者线程因虚假警报而被唤醒,并且尝试从队列中获取某些内容,而无需进一步检查队列是否为空或者没有可能出现意外结果。

这里是在Java中调用wait,notify和notifyAll方法的标准成语:

如何在Java中调用wait方法:

synchronized (object) {
         while ()
             object.wait();
         ... // Perform action appropriate to condition
 }

 这里是使用两个线程(生产者和消费者)在Java中调用wait和notify方法的完整示例

 

 Java Inter Thread通信示例 - 等待并通知

Java内部线程通信示例等待通知方法我们有一个共享的队列和两个称为生产者和消费者的线程。生产者线程将数字放入共享队列中,而使用者线程使用共享存储区中的数字。条件是,一旦产生了一个项目,就必须通知消费者线程,并在需要通知消费生产者线程之后进行通知。这种线程间通信是使用等待和通知方法实现的。记住等待和通知方法是在对象类中定义的,并且它们必须在同步块内部调用。

package concurrency;
import java.util.LinkedList;
import java.util.Queue;
import org.apache.log4j.Logger;

public class InterThreadCommunicationExample {

    public static void main(String args[]) {

        final Queue sharedQ = new LinkedList();

        Thread producer = new Producer(sharedQ);
        Thread consumer = new Consumer(sharedQ);

        producer.start();
        consumer.start();

    }
}

public class Producer extends Thread {
    private static final Logger logger = Logger.getLogger(Producer.class);
    private final Queue sharedQ;

    public Producer(Queue sharedQ) {
        super("Producer");
        this.sharedQ = sharedQ;
    }

    @Override
    public void run() {

        for (int i = 0; i < 4; i++) {

            synchronized (sharedQ) {
                //waiting condition - wait until Queue is not empty
                while (sharedQ.size() >= 1) {
                    try {
                        logger.debug("Queue is full, waiting");
                        sharedQ.wait();
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                logger.debug("producing : " + i);
                sharedQ.add(i);
                sharedQ.notify();
            }
        }
    }
}

public class Consumer extends Thread {
    private static final Logger logger = Logger.getLogger(Consumer.class);
    private final Queue sharedQ;

    public Consumer(Queue sharedQ) {
        super("Consumer");
        this.sharedQ = sharedQ;
    }

    @Override
    public void run() {
        while(true) {

            synchronized (sharedQ) {
                //waiting condition - wait until Queue is not empty
                while (sharedQ.size() == 0) {
                    try {
                        logger.debug("Queue is empty, waiting");
                        sharedQ.wait();
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                int number = sharedQ.poll();
                logger.debug("consuming : " + number );
                sharedQ.notify();
              
                //termination condition
                if(number == 3){break; }
            }
        }
    }
}

Output:
05:41:57,244 0    [Producer] DEBUG concurrency.Producer  - producing : 0
05:41:57,260 16   [Producer] DEBUG concurrency.Producer  - Queue is full, waiting
05:41:57,260 16   [Consumer] DEBUG concurrency.Consumer  - consuming : 0
05:41:57,260 16   [Consumer] DEBUG concurrency.Consumer  - Queue is empty, waiting
05:41:57,260 16   [Producer] DEBUG concurrency.Producer  - producing : 1
05:41:57,260 16   [Producer] DEBUG concurrency.Producer  - Queue is full, waiting
05:41:57,260 16   [Consumer] DEBUG concurrency.Consumer  - consuming : 1
05:41:57,260 16   [Consumer] DEBUG concurrency.Consumer  - Queue is empty, waiting
05:41:57,260 16   [Producer] DEBUG concurrency.Producer  - producing : 2
05:41:57,260 16   [Producer] DEBUG concurrency.Producer  - Queue is full, waiting
05:41:57,260 16   [Consumer] DEBUG concurrency.Consumer  - consuming : 2
05:41:57,260 16   [Consumer] DEBUG concurrency.Consumer  - Queue is empty, waiting
05:41:57,260 16   [Producer] DEBUG concurrency.Producer  - producing : 3
05:41:57,276 32   [Consumer] DEBUG concurrency.Consumer  - consuming : 3

这就是使用wait和notify方法的Java中的线程间通信的简单示例。您可以看到生产者线程和使用者线程正在相互通信并使用共享队列共享数据,当消费者准备好消费时,生产者会通知消费者,消费者线程告知生产者消费完成后。这也是生产者消费者设计模式的经典例子,它本质上涉及Java中线程之间的线程间通信和数据共享。


关于“ 使用等待通知示例在Java中进行线程间通信 的评论

发表评论