ArrayBlockingQueue是一个由数组构成的有界阻塞队列,其常用构造方法:
//fair判断是否为公平锁,为true的话表明先进入的线程优先访问数据
public ArrayBlockingQueue(int capacity, boolean fair) {
// 初始容量必须大于0
if (capacity <= 0)
throw new IllegalArgumentException();
// 初始化数组
this.items = new Object[capacity];
// 初始化可重入锁
lock = new ReentrantLock(fair);
// 初始化等待条件
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
public class ArrayBlockQueueTest {
/**
* @param args
* 基于ArrayBlockQueue实现的生产者消费者模型
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayBlockingQueue<Integer>queue=new ArrayBlockingQueue<>(100, true);
ArrayBlockQueueTest test=new ArrayBlockQueueTest();
test.new Produce(queue).start();
test.new Consumer(queue).start();
}
public class Produce extends Thread{
/**
* @param queue
*/
public Produce(ArrayBlockingQueue<Integer> queue) {
super();
this.queue = queue;
}
private ArrayBlockingQueue<Integer> queue;
@Override
public void run(){
try {
while (true) {
System.out.println("消费端消费"+queue.take());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Consumer extends Thread{
/**
* @param queue
*/
public Consumer(ArrayBlockingQueue<Integer> queue) {
super();
this.queue = queue;
}
private ArrayBlockingQueue<Integer> queue;
@Override
public void run(){
int i=0;
while (i<1000000) {
System.out.println("添加元素"+i);
try {
queue.put(i++);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
这里重点关注下ArrayBlockingQueue的put方法和add方法。
put方法是存入元素,如果满的话就休眠线程等待。
add方法最终盗用的是offer方法,offer方法是插入,如果满的话就等待,并返回false。而add方法判断offer返回false后,会报错IllegalStateException。所以在生产消费者模型中用offer或者put,不要用add
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
1. put函数
说明:put函数用于存放元素,在当前线程被中断时会抛出异常,并且当队列已经满时,会阻塞一直等待。其中,put会调用enqueue函数,enqueue函数源码如下
2. offer函数
说明:offer函数也用于存放元素,在调用ArrayBlockingQueue的add方法时,会间接的调用到offer函数,offer函数添加元素不会抛出异常,当底层Object数组已满时,则返回false,否则,会调用enqueue函数,将元素存入底层Object数组。并唤醒等待notEmpty条件的线程。
3. take函数
说明:take函数用于从ArrayBlockingQueue中获取一个元素,其与put函数相对应,在当前线程被中断时会抛出异常,并且当队列为空时,会阻塞一直等待。其中,take会调用dequeue函数,dequeue函数源码如下
说明:dequeue函数用于将取元素,并且会唤醒等待notFull条件的线程。
4. poll函数
说明:poll函数用于获取元素,其与offer函数相对应,不会抛出异常,当元素个数为0是,返回null,否则,调用dequeue函数,并唤醒等待notFull条件的线程。并返回。
5. clear函数
说明:clear函数用于清空ArrayBlockingQueue,并且会释放所有等待notFull条件的线程(存放元素的线程)。