ArrayBlockingQueue实现生产者消费者模型

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函数  

扫描二维码关注公众号,回复: 183367 查看本文章

  说明:clear函数用于清空ArrayBlockingQueue,并且会释放所有等待notFull条件的线程(存放元素的线程)。

猜你喜欢

转载自blog.csdn.net/andyzhu_2005/article/details/79962090