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

      

  • 相关阅读:
    python数据采集与多线程效率分析
    Memcache使用基础
    《大规模 web服务开发》笔记
    画了一张PHPCMSV9的运行流程思维导图
    MySQL的正则表达式
    linux patch 格式与说明(收录)
    Memcached笔记之分布式算法
    bzoj 2120 带修改莫队
    bzoj 2073 暴力
    bzoj 1814 Ural 1519 Formula 1 插头DP
  • 原文地址:https://www.cnblogs.com/dquery/p/7074754.html
Copyright © 2011-2022 走看看