• 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

      

  • 相关阅读:
    Java实现 洛谷 P1060 开心的金明
    (Java实现) 洛谷 P1605 迷宫
    (Java实现) 洛谷 P1605 迷宫
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
    Java实现 洛谷 P1064 金明的预算方案
    (Java实现) 洛谷 P1031 均分纸牌
    QT树莓派交叉编译环开发环境搭建(附多个exe工具下载链接)
    武则天红人对唐睿宗的桃色报复(如此缺少城府,注定了要在宫廷中过早地出局)
  • 原文地址:https://www.cnblogs.com/dquery/p/7074754.html
Copyright © 2020-2023  润新知