import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BlockingQueue<T> {
/**
* 對象池
*/
private Object[] objs;
/**
* 容量
*/
private int capacity = DEFAULT_CAPACITY;
/**
* 存元素的索引
*/
private int putIndex = 0;
/**
* 取元素的索引
*/
private int takeIndex = 0;
/**
* 元素個數
*/
private int curLen = 0;
/**
* 併發鎖
*/
private Lock lock = new ReentrantLock();
/**
* 隊列有元素
*/
private Condition notNullCondition = lock.newCondition();
/**
* 隊列有空間
*/
private Condition notFullCondition = lock.newCondition();
/**
* 默認容量大小
*/
private static final int DEFAULT_CAPACITY = 100;
public BlockingQueue(int capacity) {
if (capacity > 0) {
this.capacity = capacity;
}
objs = new Object[this.capacity];
}
public void push(T obj) throws InterruptedException {
try {
lock.lock();
// 容量已滿,阻塞等待
while (curLen == capacity) {
System.out.println("Queue is full...");
notFullCondition.await();
}
// 放置元素
objs[putIndex] = obj;
curLen++;
// 索引更新
putIndex++;
if (putIndex >= capacity) {
putIndex = 0;
}
// 通知消費者線程
notNullCondition.signalAll();
} finally {
lock.unlock();
}
}
public T poll() throws InterruptedException {
Object obj;
try {
lock.lock();
// 隊列未空,阻塞等待
while (curLen == 0) {
System.out.println("Queue is empty...");
notNullCondition.await();
}
// 獲取元素
obj = objs[takeIndex];
curLen--;
// 索引更新
takeIndex++;
if (takeIndex >= capacity) {
takeIndex = 0;
}
// 通知生產者線程
notFullCondition.signalAll();
} finally {
lock.unlock();
}
return (T) obj;
}
public static void main(String args[]) throws InterruptedException {
BlockingQueue queue = new BlockingQueue(5);
// 正常的入隊、出隊
queue.push(1);
System.out.println(queue.poll());
queue.push(2);
System.out.println(queue.poll());
queue.push(3);
System.out.println(queue.poll());
// 持續入隊
queue.push(1);
queue.push(2);
queue.push(3);
queue.push(4);
queue.push(5);
// 這裏會阻塞
// queue.push(6);
// 持續出隊
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
// 這裏會阻塞
// System.out.println(queue.poll());
}
}