生产者消费者代码实现之wait和notify详解

下面是一段关于生产者和消费者的代码详解

总体思路是:生产者负责往数据池里面放入数据,消费者负责从尺子里取数据,其中的尺子指的是ConCurrentBlockQueue,自己实现的同步阻塞队列

如果生产者生产的数据少,而需要消费的数据多,那么这个程序会被阻塞,可以调节producerCount和ConsumerCount的数量检查同步容器的阻塞情况

代码有详细的注释

package com.lyzx.concurrent.day01;


import java.util.LinkedList;
import java.util.Queue;

/**
 * 同步阻塞队列的实现,实现3个方法:
 * get-获取一个值
 * put-放入一个值
 * size-获取当前容器中元素的个数
 * @param <T>
 */
public class ConCurrentBlockQueue<T>{
    private Queue<T> q = new LinkedList<>();
    private int count = 0;
    private int MAX = 20;

    /**
     * 需要注意的
     * 点1:使用while而不是用if
     *   >> 当线程A获取锁正在执行count==0后,发现count==0为true
     *   >> 则进入等待,此时线程B也执行相同的操作后进入等待,当线程A再次
     *   >> 获取锁之后就出了if判读直接往后走count-- ,count就等于-1了
     *   >> 而使用while后,从wait中醒来在判断一次条件是否成立,如果成立则
     *   >> 继续等待,从而解决了这个问题
     * 点2:this.notifyAll();
     *   这是一个同步的阻塞的队列,注意是阻塞的,当元素个数为0时,可能有两个
     *   线程在等待获取元素,当放入一个元素时应该很快被取走,所以要通知在这个对象(ConCurrentBlockQueue类的实例)
     *   上等待的所有线程,当然包括等待取元素的线程,让其取走元素
     * @return
     */
    public synchronized T get(){
        while(count == 0){
            try {
                this.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        count--;
        this.notifyAll();
        return q.poll();
    }


    public synchronized void put(T item){
        while(count == MAX){
            try {
                this.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        count++;
        this.notifyAll();
        q.add(item);
        System.out.println(Thread.currentThread().getName()+" 放入元素 "+item);
    }

    public synchronized int size(){
        return count;
    }



    public static void main(String[] args) {
        ConCurrentBlockQueue<String> q = new ConCurrentBlockQueue<>();
        Runnable in = ()->{
            for(int i=0;i<10;i++){
                q.put("_"+i);
            }
        };

        Runnable out = ()->{
            for(int i=0;i<5;i++){
                System.out.println(Thread.currentThread().getName()+" 取出:"+q.get());
            }
        };

	int producerCount = 5;
        for(int i=0;i<producerCount ;i++){
            new Thread(in,"C"+i).start();
        }
	
	int consumerCount = 10;
        for(int i=0;i<consumerCount;i++){
            new Thread(out,"P:"+i).start();
        }
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值