ArrayBlockingQueue使用示例
package queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ArrayBlockingQueueTest {
/**
* 创建容量大小为1的有界队列
*/
private BlockingQueue<queue.Ball> blockingQueue = new ArrayBlockingQueue<Ball>(1);
/**
* 队列大小
* @return
*/
public int queueSize(){
return blockingQueue.size();
}
/**
* 将球放入队列当中,生产者
* @param ball
* @throws InterruptedException
*/
public void produce(Ball ball) throws InterruptedException{
blockingQueue.put(ball);
}
/**
* 将球从队列当中拿出去,消费者
* @return
*/
public Ball consume() throws InterruptedException {
return blockingQueue.take();
}
public static void main(String[] args){
final ArrayBlockingQueueTest box = new ArrayBlockingQueueTest();
ExecutorService executorService = Executors.newCachedThreadPool();
/**
* 往箱子里面放入乒乓球
*/
executorService.submit(new Runnable() {
public void run() {
int i = 0;
for(int j=0;j<10;j++){
Ball ball = new Ball();
ball.setNumber("乒乓球编号:"+i);
ball.setColor("yellow");
try {
long man=System.currentTimeMillis();
System.out.println(man +
":准备往箱子里放入乒乓球:--->" + ball.getNumber());
box.produce(ball);
System.out.println(man +
":往箱子里放入乒乓球:--->" + ball.getNumber());
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
});
/**
* consumer,负责从箱子里面拿球出来
*/
executorService.submit(new Runnable() {
public void run() {
for(int i=0;i<10;i++){
try {
long man=System.currentTimeMillis();
System.out.println(man +
"准备到箱子中拿乒乓球:--->");
Ball ball = box.consume();
System.out.println(man +
"拿到箱子中的乒乓球:--->" + ball.getNumber());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
}
构造函数
capacity:队列的大小(items数组的长度),fair:为false时reentrantLock为非公平锁,为true时为公平锁
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();
notFull = lock.newCondition();
}
//将集合c中的元素存到ArrayBlockingQueue中
public ArrayBlockingQueue(int capacity, boolean fair,
Collection<? extends E> c){
...
}
ArrayBlockingQueue的属性
- final Object[] items : 保存放入队列中的元素
- int takeIndex :下一次使用 take、poll、peek或者remove方法时操作的元素的索引
- int putIndex : 下一次使用put、offer或者add方法时添加的元素在items中的索引
- int count :items中储存的元素的数量
- final ReentranLock lock
- private final Condition notEmpty:Condition for waiting takes
- private final Condition notFull:Condition for waiting puts
put()
在BlockingQueue接口中申明
/**
*将指定的元素插入队列,队列中没有空间时会进行等待
*/
void put(E e) throws InterruptedException;
在ArrayBlockingQueue中的实现
/**
*将指定的元素插入到队列的队尾,当队列满了后将等待空间提供
*/
public void put(E e) throws InterruptedException {
Objects.requireNonNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
requireNonNull()
Objects类中定义的静态方法:检查指定的Object是否为null
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
await()
在Condition接口中定义:让当前线程进行等待,直到收到信号或者被中断
/**
* Causes the current thread to wait until it is signalled or
* {@linkplain Thread#interrupt interrupted}.
*/
void await() throws InterruptedException;
在AbstractQueueSynchronizer中实现:实现可中断条件等待
/**
* Implements interruptible condition wait.
* <ol>
* <li>If current thread is interrupted, throw InterruptedException.
* <li>Save lock state returned by {@link #getState}.
* <li>Invoke {@link #release} with saved state as argument,
* throwing IllegalMonitorStateException if it fails.
* <li>Block until signalled or interrupted.
* <li>Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
* <li>If interrupted while blocked in step 4, throw InterruptedException.
* </ol>
*/
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);//释放全部的独占锁,如果节点失效,将节点的ws设置为cancelled
int interruptMode = 0;
//判断条件队列中的node是否在同步队列中
while (!isOnSyncQueue(node)) {
LockSupport.park(this);//阻塞当前线程
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
//走到这里说明节点已经条件满足被加入到了同步队列或者中断了
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
//走到这里说明已经成功获取了独占锁,
//删除条件队列中被取消的节点
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
//等于0是唤醒返回,非正常中断方式中,抛出异常,如果是中断之后在被唤醒,线程进行自我中断
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
addConditionWaiter()
将新的等待线程加入到等待队列中
/**
* Adds a new waiter to wait queue.
* @return its new wait node
*/
private Node addConditionWaiter() {
if (!isHeldExclusively())//判断当前线程是否独占锁 getExclusiveOwnerThread() == Thread.currentThread()
throw new IllegalMonitorStateException();
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
//等待队列中的node的waitStatus只有Condition和cancelled两种状态
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();//删除等待队列中waitStatus!=Node.CONDITION的节点
t = lastWaiter;
}
/**
*Node(int waitStatus) {
* WAITSTATUS.set(this, waitStatus);
* THREAD.set(this, Thread.currentThread());
*/}
Node node = new Node(Node.CONDITION);
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}
fullConditionWaiter()
/**
* Invokes release with current state value; returns saved state.
* Cancels node and throws exception on failure.
* @param node the condition node for this wait
* @return previous sync state
*/
final int fullyRelease(Node node) {
try {
int savedState = getState();//得到当前独占锁的加锁次数
if (release(savedState))//一次性全部释放
return savedState;
throw new IllegalMonitorStateException();
} catch (Throwable t) {
//失败时将node的waitStatus设置为Node.CANCELLED,标记该节点已失效
node.waitStatus = Node.CANCELLED;
throw t;
}
}
isOnSynQueue()
判断在条件队列中的节点现在是否在同步队列中等待被释放
虽然同步队列和条件队列都是使用AQS中的Node类来实现的,但是同步队列是双向链表,使用Node类中的next和prev属性;条件队列是单项链表,使用Node类中的nextWaiter属性,
/**
* Returns true if a node, always one that was initially placed on
* a condition queue, is now waiting to reacquire on sync queue.
* @param node the node
* @return true if is reacquiring
*/
final boolean isOnSyncQueue(Node node) {
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
if (node.next != null) // If has successor, it must be on queue
return true;
/*
* node.prev can be non-null, but not yet on queue because
* the CAS to place it on queue can fail. So we have to
* traverse from tail to make sure it actually made it. It
* will always be near the tail in calls to this method, and
* unless the CAS failed (which is unlikely), it will be
* there, so we hardly ever traverse much.
*/
//在队列中从后往前遍历,判断node是否在同步队列中存在
return findNodeFromTail(node);
}
checkInterruptWhileWaiting()
/**
* Checks for interrupt, returning THROW_IE if interrupted
* before signalled, REINTERRUPT if after signalled, or
* 0 if not interrupted.
*/
private int checkInterruptWhileWaiting(Node node) {
return Thread.interrupted() ?
(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
0;//
}
final boolean transferAfterCancelledWait(Node node) {
//将node的ws设置为初始值:0,设置为0是进入同步队列的先决条件,
if (node.compareAndSetWaitStatus(Node.CONDITION, 0)) {
enq(node);//将node加入同步队列
/**
*private Node enq(Node node) {
* for (;;) {
* Node oldTail = tail;
* if (oldTail != null) {
* node.setPrevRelaxed(oldTail);
* if (compareAndSetTail(oldTail, node)) {
* oldTail.next = node;
* return oldTail;
* }
* } else {
* initializeSyncQueue();
* }
* }
*}
*/
return true;
}
// 判断是否在同步队列中,否则让此线程处于一直让渡资源
while (!isOnSyncQueue(node))
//Thread.yield()方法作用是:暂停当前正在执行的线程对象(及放弃当前拥有的cup资源),并执行其他线程。
Thread.yield();
return false;
}
unlinkCancelledWaiters()
从条件队列中删除waitStatus!=Condition的节点
private void unlinkCancelledWaiters() {
Node t = firstWaiter;
Node trail = null;
while (t != null) {
Node next = t.nextWaiter;
if (t.waitStatus != Node.CONDITION) {
t.nextWaiter = null;
if (trail == null)
firstWaiter = next;
else
trail.nextWaiter = next;
if (next == null)
lastWaiter = trail;
}
else
trail = t;
t = next;
}
}
reportInterruptAfterWait()
/**
* Throws InterruptedException, reinterrupts current thread, or
* does nothing, depending on mode.
*/
private void reportInterruptAfterWait(int interruptMode)
throws InterruptedException {
if (interruptMode == THROW_IE)
throw new InterruptedException();
else if (interruptMode == REINTERRUPT)
selfInterrupt();
}