给定一个(ArrayList)将其改写成一个简单的阻塞队列,要求拥有put和get方法,以及getSize方法,能够支持多个生产者和多个消费者线程拥塞调用。
1】使用synchronized锁或ReentrantLock锁实现
1】使用Object的wait、notify、notifyAll来实现
基本思路:使用put方法向容器中添加元素,使用get方法从容器中取出元素,在使用put方法添加元素的时候进行判断,如果容器已经满了,此时调用wait()方法,使用添加线程阻塞,等待消费线程取出元素,腾出容器空间后才能再向其中添加元素,同理当使用get方法获取元素的时候,如果容器已经为空,此时要调用wait()方法,使得取出元素线程阻塞,等待添加线程添加元素,容器不为空时才能再从容器中取出元素
public class MyArrayBlockingQueue<T>{ /* * 调用无参构造方法,阻塞队列的默认长度 */ public static final int SIZE_VALUE=10; /* * 队列的容器存放队列的元素 */ public final List<T> lists=new ArrayList<>(); /* * 队列的最大容量 */ private final int maxSize; /* * 队列当前元素个数 */ private int size=0; public MyArrayBlockingQueue() { super(); this.maxSize=SIZE_VALUE; } /** * 带参构造方法,创建时可设定队列最大元素 * @param maxSize 队列最大元素数量 */ public MyArrayBlockingQueue(int maxSize) { this.maxSize = maxSize; } /** * 生产者向容器中插入元素时调用的方法 * @param t 传入队列中的元素 * @throws InterruptedException 向上抛出线程中断的异常 */ public synchronized void put(T t) throws InterruptedException { while (lists.size()==maxSize) { System.out.println("队列中元素数量为"+maxSize+"个,队列进入则阻塞状态"); this.wait(); } lists.add(t); ++size; System.out.println("生产元素中元素数量size:"+size+" "); this.notifyAll();//唤醒消费线程进行消费 } /** * 消费者从容器中取元素时调用的方法 */ public synchronized T get() { T t=null; while(lists.size()==0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } t=lists.get(0); lists.remove(0); --size; System.out.println("消费容器中元素数量为size:"+size+" "); this.notifyAll();//唤醒生产线程进行生产 return t; } /** * 队列当前元素数量 */ public int getSize() { return size; } }
测试结果:
第一次测试,发现取出的数据都是0;后来检查了一下,是在get方法中,忘记将取出的元素remove掉了,导致取到的值都是0,有点粗心了;
使用其他的集合累的话,也可以转换成阻塞队列,大家也可以试一试