设计思路
BoundedQueue boundedQueue = new BoundedQueue(2);
BoundedQueue 初始化,并设置队列的大小 count 为 2
add(T t),往队列中添加元素,如果队列中的长度不大于 count的值,直接加入队列,唤醒等待队列的线程(消费队列中的数据),如果此时队列满了,等待(等待队列消费之后唤醒)
添加元素,如果此时队列满了,需要等待 await(),当成功添加一个元素,需要唤醒其他消费队列 signal()
remove(),从队列中取出数据,如果此时队列为空的话,需要等待(需要等待添加队列的线程添加元素之后唤醒),如果队列不为空的话,拿出一个元素来处理,然后然后唤醒添加队列(此时可能队列为满,消费一个元素,需要唤醒添加队列,往队列中添加元素)
消费元素,如果此时队列为空,等待 await(),当消费一个元素,需要唤醒其他队列添加元素 signal()
public class BoundedQueue<T> {
private Object[] items;
private int addIndex, removeIndex, count;
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
public BoundedQueue(int size) {
items = new Object[size];
}
public void add(T t) throws InterruptedException {
lock.lock();
// 获取到锁之后尝试添加元素
try {
while (count == items.length) {
notFull.await();
}
items[addIndex] = t;
// 添加的元素为队列最后一个元素时,将添加的下标置为0,循环队列
/*addIndex = (addIndex+1)%items.length*/
if (++addIndex == items.length) {
addIndex = 0;
}
count++;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public T remove() throws InterruptedException {
lock.lock();
try {
while (count == 0) {
notEmpty.await();
}
Object x = items[removeIndex];
if (++removeIndex == items.length) {
removeIndex = 0;
}
count--;
notFull.signal();
return (T) x;
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
BoundedQueue boundedQueue = new BoundedQueue(2);
new Thread(()->{
IntStream.range(0,20).forEach(i->{
try{
System.out.println("add -> " + i);
boundedQueue.add(i);
} catch (Exception e){
e.printStackTrace();
}
});
}).start();
new Thread(()->{
while (boundedQueue.items.length != 0){
try{
Object value = boundedQueue.remove();
System.out.println("remove -> " + value);
} catch (Exception e){
e.printStackTrace();
}
}
}).start();
System.out.println("main \t" + Thread.currentThread().getName());
}
}
测试
创建有界队列的大小是 2
两个线程,一个添加元素1到10,一个消费队列,结果显示如下
main main
add -> 0
add -> 1
remove -> 0
add -> 2
add -> 3
add -> 4
remove -> 1
remove -> 2
remove -> 3
add -> 5
remove -> 4
add -> 6
remove -> 5
add -> 7
remove -> 6
add -> 8
remove -> 7
add -> 9
remove -> 8
remove -> 9