最近想学习JUC的内容,就先攻克一下队列吧,平时自己用queue的场景较少,倒是了解过有很多东西是基于queue的,比如消息中间件啊。还是从常用的一些方法入手。
1.构造函数:ArrayBlockingQueue (int capacity)
public ArrayBlockingQueue(int capacity) {
this(capacity, false);
}
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
//初始化数组的长度
this.items = new Object[capacity];
//可重入锁,设置为非公平锁
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();//非空condition
notFull = lock.newCondition();//非满condition
}
2.add(E e)增加一个元索 。如果队列已满,则抛出一个IIIegaISlabEepeplian异常
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
//添加一个元素并返回true 如果队列已满,则返回false
public boolean offer(E e) {
checkNotNull(e);//检查e是否为null
//保证线程安全,同步
final ReentrantLock lock = this.lock;
lock.lock();
try {
//判断数组容量是否已满
if (count == items.length)
return false;
else {
enqueue(e);
return true;
}
} finally {
lock.unlock();
}
}
private void enqueue(E x) {
final Object[] items = this.items;
items[putIndex] = x;
//如果数组容量满了,那么 putIndex(下一次放入的位置)设置为0
//记录下次放进去的位置,是从头到尾:有点类似与指针一样
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();//非空 线程唤醒
}
3.remove() 移除并返回队列头部的元素。如果队列为空,则抛出一个NoSuchElementException异常
public E remove() {
E x = poll();
if (x != null)
return x;
else
throw new NoSuchElementException();
}
//移除并返问队列头部的元素 如果队列为空,则返回null
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return (count == 0) ? null : dequeue();
} finally {
lock.unlock();
}
}
private E dequeue() {
final Object[] items = this.items;
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
//记录下次拿出来的位置
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal();//非满 线程唤醒
return x;
}
4.peek() 返回队列头部的元素。如果队列为空,则返回null
public E peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
//takeIndex是 下一个应该被拿出来的下标
return itemAt(takeIndex); // null when queue is empty
} finally {
lock.unlock();
}
}
final E itemAt(int i) {
return (E) items[i];
}
5.put(E e)
添加一个元素。如果队列满,则阻塞public void put(E e) throws InterruptedException {
//检查e是否为null
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();//可中断地获取锁
try {
while (count == items.length)
notFull.await();//当前线程等待
enqueue(e);
} finally {
lock.unlock();
}
}
6.take() 移除并返回队列头部的元素 ,如果队列为空,会阻塞
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();//可中断地获取锁
try {
while (count == 0)
notEmpty.await();//当前线程挂起
return dequeue();
} finally {
lock.unlock();
}
}