使用wait notify实现生产者消费者模型

一个内存队列,多个生产者线程往内存队列中放数据;多个消费者线程从内存队列中取数据
在这里插入图片描述
使用wait()与notify()机制
队列的实现

public class MyQueue {
    /**
     * 数组队列(总长度为10)
     */
    private String[] data = new String[10];
    /**
     * 出队列的下标
     */
    private int getIndex = 0;
    /**
     * 入队列的下标
     */
    private int putIndex = 0;
    /**
     * 队列已使用的长度
     */
    private int size = 0;

    /**
     * 入队列前尝试获取锁
     * @param element
     */
    public synchronized void put(String element) {
        /**
         * 进入方法表示已经获取到了锁
         * 判断是否达到了队列的最大长度,如果达到了最大长度则wait,如果没有则进行put0的入队列逻辑,入队列完成后notify唤醒其他线程
         */
        if (size == data.length) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //这里从wait状态被唤醒后需要重新进入put方法判断是否达到队列的最大长度
            put(element);
        } else {
            put0(element);
            notify();
        }
    }

    /**
     * 入队列
     * @param element
     */
    private void put0(String element) {
        //把当前element放进队列,然后putIndex下标+1
        data[putIndex] = element;
        ++putIndex;
        //如果putIndex到达数组尾部,则重新从队列头开始存入
        if (putIndex == data.length) {
            putIndex = 0;
        }
        ++size;
    }

    /**
     * 出队列前尝试获取锁
     * @return
     */
    public synchronized String get() {
        //判断队列是否已经空了
        //如果空了则等待
        if (size == 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //被唤醒,然后重新判断是否是空队列
            return get();
        } else {
            //出队列
            String result = get0();
            //唤醒其他线程
            notify();
            return result;
        }
    }

    /**
     * 出队列
     * @return
     */
    private String get0() {
        //依次从getIndex向后取,这次取getIndex的,下次进入get0方法就取getIndex+1的
        String result = data[getIndex];
        ++getIndex;
        //如果getIndex到达数组的最大值,则从队列头开始取
        if (getIndex == data.length) {
            getIndex = 0;
        }
        --size;
        return result;
    }
}

生产者

/**
 * 生产者
 */
public class ProducerThread extends Thread {
    private final MyQueue myQueue;
    private final Random random = new Random();
    private int index = 0;


    public ProducerThread(MyQueue myQueue) {
        this.myQueue = myQueue;
    }

    @Override
    public void run() {
        //不停的生产
        while (true) {
            String tmp = "ele-"+Thread.currentThread().getName()+"-" + index;
            //put方法有synchronize,锁的是myQueue自己
            myQueue.put(tmp);
            System.out.println("添加元素:" + tmp);
            index++;
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

消费者

/**
 * 消费者
 */
public class ConsumerThread extends Thread {
    private final MyQueue myQueue;
    private final Random random = new Random();

    
    public ConsumerThread(MyQueue myQueue) {
        this.myQueue = myQueue;
    }

    @Override
    public void run() {
        while (true) {
            //get方法有synchronize,锁的是myQueue自己
            String s = myQueue.get();
            System.out.println("\t\t消费元素:" + s);
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

测试代码

public class Main {
    public static void main(String[] args) {
        MyQueue myQueue = new MyQueue();
        for (int i = 0; i < 3; i++) {
            //消费者消费同一个队列
            new ConsumerThread(myQueue).start();
        }
        for (int i = 0; i < 5; i++) {
            //生产者放入同一个队列
            new ProducerThread(myQueue).start();
        }
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值