使用wait和notify实现非阻塞生产消费者模型

1. wait notify notifyAll

wait notify notifyAll 调用必须是获取锁对象的时候调用才有效果,否则会抛出异常,需要配置synchronized一起使用;

  • wait: 释放线程锁,并使当前线程进入休眠状态;
  • notify: 唤醒一个wait状态的线程,进去争抢锁资源的队列;
  • notifyAll: 唤醒所有争抢当前锁的线程,并且这个线程处于wait状态;

2. 实现逻辑

  1. 首先有一个队列;
  2. 生产者生产到队列上限以后停止生产,唤醒消费者进行消费,自身进入休眠状态;
  3. 消费者开始消费队列,直到队列消费完,然后唤醒生产者进行生产,自身进入休眠状态;

3. 代码

package com.cans.product;


import java.util.LinkedList;

/**
 * 商品库
 *
 * @author shenc
 * @date 2023-01-21 17:23
 **/
public class GoodsStack {


    /**
     * 队列最大值
     */
    private static final int COUNT = 5;

    private static volatile Boolean isStop = false;

    private static final LinkedList<String> products = new LinkedList<>();

    public static void main(String[] args) {

        Thread makeThread = new Thread(new ProductMake());
        Thread consumerThread = new Thread(new ProductConsumer());

        makeThread.start();
        consumerThread.start();

    }

    /**
     * 生产者
     */
    public static class ProductMake implements Runnable {

        @Override
        public void run() {
            int i = 0;
            // 生产总数
            int count = 20;
            while (i < count) {
                synchronized (products) {
                    while (products.size() >= COUNT) {
                        products.notifyAll();
                        try {
                            products.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    String goods = "P:" + ++i;
                    products.add(goods);
                    if(i == count){
                        products.notifyAll();
                    }
                    System.out.println(Thread.currentThread().getName() + "生产商品:" + goods);
                }
            }
            isStop = true;
        }
    }

    public static class ProductConsumer implements Runnable {
        @Override
        public void run() {
            synchronized (products) {
                while (true) {
                    while (products.isEmpty()){
                        if(Boolean.TRUE.equals(isStop)){
                            return;
                        }
                        products.notifyAll();
                        try {
                            products.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    String goods = products.removeFirst();
                    System.out.println(Thread.currentThread().getName() + "消费商品:" + goods);
                }
            }
        }
    }
}

运行结果:

Thread-0生产商品:P:1
Thread-0生产商品:P:2
Thread-0生产商品:P:3
Thread-0生产商品:P:4
Thread-0生产商品:P:5
Thread-1消费商品:P:1
Thread-1消费商品:P:2
Thread-1消费商品:P:3
Thread-1消费商品:P:4
Thread-1消费商品:P:5
Thread-0生产商品:P:6
Thread-0生产商品:P:7
Thread-0生产商品:P:8
Thread-0生产商品:P:9
Thread-0生产商品:P:10
Thread-1消费商品:P:6
Thread-1消费商品:P:7
Thread-1消费商品:P:8
Thread-1消费商品:P:9
Thread-1消费商品:P:10
Thread-0生产商品:P:11
Thread-0生产商品:P:12
Thread-0生产商品:P:13
Thread-0生产商品:P:14
Thread-0生产商品:P:15
Thread-1消费商品:P:11
Thread-1消费商品:P:12
Thread-1消费商品:P:13
Thread-1消费商品:P:14
Thread-1消费商品:P:15
Thread-0生产商品:P:16
Thread-0生产商品:P:17
Thread-0生产商品:P:18
Thread-0生产商品:P:19
Thread-0生产商品:P:20
Thread-1消费商品:P:16
Thread-1消费商品:P:17
Thread-1消费商品:P:18
Thread-1消费商品:P:19
Thread-1消费商品:P:20

4. 总结

  1. 使用wait以后当前线程进入休眠状态并且会阻塞当前线程,但是不会消耗CPU资源,这样会提高CPU的利用率;

你可能感兴趣的:(java多线程,面试,JAVA,java,面试,多线程)