wait、notify应用场景(生产者-消费者模式)

Java实现生产者消费者的方式有:wait && notify、BlockingQueue、Lock && Condition等

wait、notify注意事项:
(1)可以使用wait()和notify()方法在Java中实现线程间通信。不只是一个或两个线程,而是多个线程可以使用这些方法相互通信。
(2)在synchronized方法或synchronized块中调用wait(),notify()和notifyAll()方法,否则JVM将抛出IllegalMonitorStateException。
(3)从while(条件)循环调用wait和notify方法,而不是从if()块调用,因为要重复检查条件,而不仅仅是一次。
(4)多使用notifyAll方法而不是notify。


下面是wait、notify等待通知实现的生产者-消费者模式:
生产者:

/**
 * 生产者
 *
 * @author monkjavaer
 * @date 2018/12/15 11:13
 */
public class Producer implements Runnable {
    /**
     * 产品容器
     */
    private final List<Integer> container;

    public Producer(List<Integer> container) {
        this.container = container;
    }

    /**
     * 生产者生产方法
     *
     * @throws InterruptedException
     */
    private void produce() throws InterruptedException {
        //产品容器容量
        int capacity = 5;
        synchronized (container) {
            //当容器已满,暂停生产
            while (container.size() == capacity) {
                System.out.println("...容器已经满了,暂停生产...");
                container.wait();
            }
            Random random = new Random();
            int p = random.nextInt(50);
            //模拟1秒生产一个产品
            TimeUnit.MILLISECONDS.sleep(1000);
            System.out.println("生产产品:" + p);
            container.add(p);
            container.notifyAll();
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                produce();
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("produce error");
            }
        }
    }
}

  消费者:

/**
 * 消费者
 * @author monkjavaer
 * @date 2018/12/15 11:13
 */
public class Consumer implements Runnable{

    /**
     * 产品容器
     */
    private final List<Integer> container;

    public Consumer(List<Integer> container) {
        this.container = container;
    }

    /**
     * 消费者消费产品
     */
    private void consume() throws InterruptedException {
        synchronized (container){
            while (container.isEmpty()){
                System.out.println("...容器是空的,暂停消费...");
                container.wait();
            }
            Integer p = container.remove(0);
            //模拟1秒消费一个产品
            TimeUnit.MILLISECONDS.sleep(1000);
            System.out.println("消费产品:" + p);
            container.notifyAll();
        }
    }
    @Override
    public void run() {
        while (true){
            try {
                consume();
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("consume error");
            }
        }
    }
}

  测试:

public class ProducerConsumerTest {
    public static void main(String[] args) {
        List<Integer> container = new ArrayList<>();
        Thread producer = new Thread(new Producer(container));
        Thread consumer = new Thread(new Consumer(container));
        producer.start();
        consumer.start();
    }
}

  输出:

生产产品:14
生产产品:17
消费产品:14
生产产品:0
生产产品:39
生产产品:4
生产产品:3
...容器已经满了,暂停生产...
消费产品:17
消费产品:0
消费产品:39
消费产品:4
消费产品:3
...容器是空的,暂停消费...
生产产品:25
生产产品:33
生产产品:17
消费产品:25
消费产品:33
消费产品:17
...容器是空的,暂停消费...

  

原文地址:https://www.cnblogs.com/monkjavaer/p/10123687.html