生产者消费者的一个面试问题

题目:写一个固定容量的同步容器,拥有put、get方法以及getCount方法,能够支持2个生产者以及10个消费者的阻塞调用。

思路
从题目可以得出这是一个同步容器,这就可以理解为该容器对象在调用过程中需要加锁,一般我们会想到synchornized,先用这个方法实现,下面是代码

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

public class Container<T> {
    final private LinkedList<T> list=new LinkedList<T>();
    final private int MAX=10;
    private int count=0;
    public synchronized void put(T t){
        /*这里必须使用while,首先wait和while经常一起使用,其次如果使用if,会出现错误数据。
        线程t一开始list.size()==MAX,线程t会wait,wait方法会释放锁.如果此时线程a执行get弄走一个数据,
        然后线程b执行put方法,发现list.size()<MAX,然后执行add方法,这个时候数据就满了,即list.size()==MAX。
        这个时候线程t被叫醒,接着wait后执行,如果这里是if的话线程t不会再去判断list.size()和MAX的大小
        其实这里已经错了,这里的list.size()和MAX已经相等了,需要t去wait但是t线程没有while判断所以出错*/
        while(list.size()==MAX){
            try {
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        count++;
        list.add(t);
        this.notifyAll();
    }
    public synchronized T get(){
        T t=null;
        while(list.size()==0){

            try {
                this.wait();  //wait()释放锁
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        t=list.removeFirst();
        count--;
        this.notifyAll();

        return t;
    }

    public int getCount(){
        return count;
    }
    public static void main(String[] args) {
        Container<String> myCon=new Container<String>();

        //10个消费者线程
        for (int i = 0; i < 10; i++) {

            Runnable c=new Runnable() {             
                @Override
                public void run() {
                    for (int j = 0; j < 5; j++) {
                        System.out.println(myCon.get());
                    }

                }
            };

            new Thread(c,"c"+i).start();
        }

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //2个生产者线程
        for (int i = 0; i < 2; i++) {

            Runnable p=new Runnable() {             
                @Override
                public void run() {
                    for (int j = 0; j < 26; j++) {
                        myCon.put(Thread.currentThread().getName()+" "+j);
                    }

                }
            };

            new Thread(p,"p"+i).start();
        }


        Runnable p=new Runnable() {             
            @Override
            public void run() {
                    System.out.println(myCon.getCount());
            }
        };

        new Thread(p,"count").start();

    }

}

总结
这里做个笔记,我感觉面试可能会碰到,所以可以收藏看看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值