zoukankan      html  css  js  c++  java
  • Java里的阻塞队列

      JDK7提供了7个阻塞队列,如下:

      ArrayBlockingQueue  : 一个数组结构组成的有界阻塞队列。

      LinkedBlockingQueue : 一个由链表结构组成的有界阻塞队列 。

      PriorityBlockingQueue : 一个支持优先级排序的无界阻塞队列 。

      DelayQueue : 一个使用优先级队列实现的无界阻塞队列 。

      SynchronousQueue : 一个不存储元素的阻塞队列 。

      LinkedTransferQueue : 一个由链表结构组成的无界阻塞队列 。

      LinkedBlockingDeque : 一个由链表结构组成的双向阻塞队列 。

      下面分别介绍几个队列 :

    1.ArrayBlockingQueue

      ArrayBlockingQueue是一个由数组结构组成的有界阻塞队列,此队列按照FIFO的原则对元素进行排序 。

      默认情况下不保证线程公平的访问队列,所谓公平的访问队列是指阻塞的线程,可以按照阻塞的先后顺序访问队列,即先阻塞线程先访问队列。非公平性是对先等待的线程是非公平的,当队列可用时,阻塞的线程都可以争夺队列的资格,有可能先阻塞的队列最后才访问队列。为了保证公平性通常都会降低吞吐量。下面的代码可以创建一个公平的阻塞队列:

    ArrayBlockingQueue fairQueue = new ArrayBlockingQueue(100,true);

      访问者的公平性是通过可重入锁实现的,构造函数如下:

        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();
        }

      ArrayBlockingQueue使用一个Object数组保存数据,一个int类型的count表示当前队列添加的元素个数,有界保证依靠的两个Condition对象,下面看一下put()方法,代码如下:

    public void put(E e) throws InterruptedException {
            checkNotNull(e);
            final ReentrantLock lock = this.lock;
            lock.lockInterruptibly();
            try {
                //判断队列是否已满
                while (count == items.length)
                    //如果已经满了,等待
                    notFull.await();
                //插入
                insert(e);
            } finally {
                lock.unlock();
            }
    }
    private void insert(E x) {
        items[putIndex] = x;
        putIndex = inc(putIndex);//加1
        ++count;
        notEmpty.signal();
    }

      ArrayBlockingQueue在执行put操作时,首先获取锁,然后判断插入队列是否已满,如果队列已满则等待,否则顺利插入,并且执行一次notEmpty.signal()唤醒有可能队列为空的情况下执行take()操作在等待的线程 ,take()方法代码如下:

    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            //如果队列为空,则等待元素入队
            while (count == 0)
                notEmpty.await();
            return extract();
        } finally {
            lock.unlock();
        }
    }
    private E extract() {
        final Object[] items = this.items;
        E x = this.<E>cast(items[takeIndex]);
        items[takeIndex] = null;
        takeIndex = inc(takeIndex);
        --count;
        notFull.signal();
        return x;
    }

       take操作也是先判断队列是否为空,为空则等待,不为空则返回items[takeIndex] ,并且执行notFull.signal()唤醒可能在等待put操作的线程。

    2.LinkedBlockingQueue

      

  • 相关阅读:
    IDEA学习和收藏夹
    mysql资料收集及学习
    一些模板代码
    docker学习
    Spring事务传播类型
    rust学习疑惑
    [重新做人]从头学习JAVA SE——java.lang.reflect
    java核心技术卷一
    Spring实战 难懂的JavaBean
    Spring实战系列
  • 原文地址:https://www.cnblogs.com/dquery/p/7074754.html
Copyright © 2011-2022 走看看