自定義阻塞隊列
這個自定義阻塞隊列基本就是jdk阻塞隊列的實現
public class MyBlockQueue<E> {
/**
* 鎖 保證併發安全
*/
private ReentrantLock lock = new ReentrantLock();
/**
* 隊列元素
*/
private final Object[] items;
/**
* 取元素的下標
*/
private int takeIndex;
/**
* 放元素的下標
*/
private int putIndex;
/**
* 隊列中元素的個數
*/
private int count;
/**
* 用於隊列空的時候阻塞
*/
private Condition isEmpty = lock.newCondition();
/**
* 用於隊列滿的時候阻塞
*/
private Condition isFull = lock.newCondition();
public MyBlockQueue(){
this(16);
}
public MyBlockQueue(int len) {
// 隊列長度不能小於0
if (len < 0)
throw new IllegalArgumentException("param is illegal");
this.items = new Object[len];
}
public void put(E e) throws InterruptedException {
// 加鎖
lock.lock();
try{
// 當隊列滿的時候線程阻塞
while (count == items.length)
isFull.await();
items[putIndex] = e;
// 判斷隊列是否插完,是的話就開始從第一個開始插
if (++putIndex == items.length)
putIndex = 0;
// 元素個數加1
count++;
// 每插入一個元素就要喚醒阻塞在isEmpty上的線程
isEmpty.signal();
System.out.println(Thread.currentThread().getName() + ":放入元素,當前隊列中有元素:" + count + "個");
}finally {
lock.unlock();
}
}
public E take() throws InterruptedException {
lock.lock();
try{
// 隊列爲空的時候阻塞
while (count == 0)
isEmpty.await();
E item = (E)items[takeIndex];
items[takeIndex] = null;
// 元素個數減1
count--;
// 當takeIndex和數組長度相等的時候證明數組中元素已經取完
if (++takeIndex == items.length)
takeIndex = 0;
// 保證下次取的時候數組不越界
if (takeIndex > 0) takeIndex--;
// 每獲取一個線程就要喚醒阻塞在isFull上的線程
isFull.signal();
System.out.println(Thread.currentThread().getName() + ":取出元素,當前隊列中有元素:" + count + "個");
return item;
}finally {
lock.unlock();
}
}
/**
* 獲取隊列中元素個數
* @return
*/
public int getCount() {
return count;
}
}