自己实现阻塞队列的话可以采用Object下的wait和notify方法,也可以使用Lock锁提供的Condition来实现,本文就是自己手撸的一个简单的阻塞队列,部分借鉴了JDK的源码ArrayBlockingQueue类。
1.BlockingQueue接口
public interface BlockingQueue<T> {
void put(T element) throws InterruptedException;
T take() throws InterruptedException;
}
2.数组方式实现阻塞队列
public class MJBlockingQueue<E> implements BlockingQueue<E> {
final Object[] items;
private int size;
private int count;
private int putIndex;
private int takeIndex;
final ReentrantLock lock = new ReentrantLock();
private final Condition notfull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
public MJBlockingQueue(int size) {
this.items = new Object[size];
this.size = size;
}
@Override
public void put(E element) throws InterruptedException {
if (element == null) throw new NullPointerException();
lock.lock();
try {
while (count == size) {
notfull.await();
}
items[putIndex] = element;
putIndex++;
count++;
if (putIndex == size) putIndex = 0;
notEmpty.signal();
} finally {
lock.unlock();
}
}
@Override
public E take() throws InterruptedException {
lock.lock();
try {
if (count == 0) notEmpty.await();
E element = (E) items[takeIndex];
takeIndex++;
count--;
if (takeIndex == size) takeIndex = 0;
notfull.signal();
return element;
} finally {
lock.unlock();
}
}
}
3.测试
public static void main(String[] args) throws InterruptedException {
/*
MJBlockingQueue<String> queue = new MJBlockingQueue<>(3);
new Thread(()->{
try {
String element = queue.take();//如果没有就会阻塞在这里
System.out.println("获取到了元素" + element);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
Thread.sleep(2000);
queue.put("赵一荻");
*/
MJBlockingQueue<String> queue = new MJBlockingQueue<String>(3);
new Thread(() -> {
for (int i = 0; i < 4; i++) {
try {
queue.put(String.valueOf(i));
System.out.println(Thread.currentThread().getName() + "放入" + String.valueOf(i));
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(2000);
for (int i = 0; i < 4; i++) {
String res = queue.take();
System.out.println(Thread.currentThread().getName() + "获取到" + res);
}
}