图灵学院Java架构师-VIP-BlockingQueue阻塞队列分析

阻塞队列分类有四种:

  1. ArrayBlockingQueue 由数组支持的有界队列
  2. LinkedBlockingQueue 由节点支持的可选有界队列
  3. PriorityBlockingQueue 由优先级堆支持的无界优先级队列
  4. DelayQueue 由优先级堆支持的、基于时间的调度队列

简单看一下PriorityBlockingQueue:

public class PriorityBlockingQueue extends AbstractQueue
    implements BlockingQueue, java.io.Serializable {
    private static final long serialVersionUID = 5595510919245408276L;

    private transient Object[] queue;

通过源码,我们可以看到PriorityBlockingQueue继承自AbstractQueue,实现了BlockingQueue阻塞队列接口。还有一个Object[]可扩容数组属性。

简单看一下DelayQueue

public class DelayQueue extends AbstractQueue
    implements BlockingQueue {

    private final transient ReentrantLock lock = new ReentrantLock();
    private final PriorityQueue q = new PriorityQueue();

通过源码我们可以看到DelayQueue也是继承自AbstractQueue,实现了BlockingQueue阻塞队列接口。同时通过它的属性也可以发现它基于ReentrantLock实现,还有PriorityQueue优先级队列。

BlockingQueue队列,本质上都是依赖于ReentrantLockCondition,其中Condition是在AQS里实现的。
注意:Condition只能在独占模式下使用,共享模式下不能使用

ArrayBlockingQueue的使用示例:

ArraryBlockingQueue基于数组实现,同时数组不可扩容。

public class ArrayBlockingQueueTest {
    /**
     * 创建容量大小为1的有界队列
     */
    private BlockingQueue blockingQueue = new ArrayBlockingQueue(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;
                while (true){
                    Ball ball = new Ball();
                    ball.setNumber("乒乓球编号:"+i);
                    ball.setColor("yellow");
                    try {
                        System.out.println(System.currentTimeMillis()+
                                ":准备往箱子里放入乒乓球:--->"+ball.getNumber());
                        box.produce(ball);
                        System.out.println(System.currentTimeMillis()+
                                ":往箱子里放入乒乓球:--->"+ball.getNumber());
                        System.out.println("put操作后,当前箱子中共有乒乓球:--->"
                                + box.queueSize() + "个");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    i++;
                }
            }
        });

        /**
         * consumer,负责从箱子里面拿球出来
         */
        executorService.submit(new Runnable() {
            public void run() {
                while (true){
                    try {
                        System.out.println(System.currentTimeMillis()+
                                "准备到箱子中拿乒乓球:--->");
                        Ball ball = box.consume();
                        System.out.println(System.currentTimeMillis()+
                                "拿到箱子中的乒乓球:--->"+ball.getNumber());
                        System.out.println("take操作后,当前箱子中共有乒乓球:--->"
                                + box.queueSize() + "个");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }
}

执行结果:
图灵学院Java架构师-VIP-BlockingQueue阻塞队列分析_第1张图片
从例子中,我们可以看到初始值为1,最多只能放入一个元素。当放入元素超过1时,其他放入线程需要阻塞等待。此时会唤醒消费线程,去箱子中拿球。

你可能感兴趣的:(Java)