ArrayBlockingQueue源码阅读

允许多生产消费者使用队列

JDK注释中的生产消费者代码,允许有多个生产者和多个消费者。

class Producer implements Runnable {
   private final BlockingQueue queue;
   Producer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { queue.put(produce()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   Object produce() { ... }
 }

 class Consumer implements Runnable {
   private final BlockingQueue queue;
   Consumer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { consume(queue.take()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   void consume(Object x) { ... }
 }

 class Setup {
   void main() {
     BlockingQueue q = new SomeQueueImplementation();
     Producer p = new Producer(q);
     Consumer c1 = new Consumer(q);
     Consumer c2 = new Consumer(q);
     new Thread(p).start();
     new Thread(c1).start();
     new Thread(c2).start();
   }
 }

阻塞队列几种放入元素和取出元素的区别

插入元素都不能为null,使用ReentrantLock保证线程安全。

插入元素

offer(E e)
往队列插入一个元素,如果容量足够,插入成功返回true,否则返回失败false。
add(E e)
往队列添加元素,如果容量足够,插入成功返回true,否则抛出异常。建议使用offer(E e)而不是用add(E e)。
put(E e)
往队列插入一个元素,无返回值。如果容量不够,阻塞等待。
offer(E e, long timeout, TimeUnit unit)
往队列插入一个元素,如果队列满了,等待指定时间,返回boolean。

取出元素,会移除头部元素

remove(Object o)
移除队列中的指定元素,如果有多个(equals返回true),移除一个,返回true。如果没有,返回false。
poll()
从队列移除一个元素,如果没有,返回null。
take()
从队列取出一个元素,如果队列为空,阻塞等待。
poll(time, unit)
从队列去除一个元素,如果队列为空,阻塞等待指定时间,如果仍然没有元素,返回null。

检查队列是否为空,不移除头部元素

element()
检索但不删除队列头部,如果队列为空,抛出异常。
peek()
检索但不删除队列头部,如果队列为空,返回null。

阻塞队列中,如果队列满/空,阻塞等待被唤醒的实现方式

定义

	final ReentrantLock lock;
    /** Condition for waiting takes */
    private final Condition notEmpty;
    /** Condition for waiting puts */
    private final Condition notFull;
    
	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();
    }

取出元素

	public E take() throws InterruptedException {
	    final ReentrantLock lock = this.lock;
	    lock.lockInterruptibly();
	    try {
	        while (count == 0)
	        	// 阻塞等待put()中notEmpty.signal()
	            notEmpty.await();
	        return dequeue();
	    } finally {
	        lock.unlock();
	    }
	}
	// 元素出队
	private E dequeue() {
        // assert lock.getHoldCount() == 1;
        // assert items[takeIndex] != null;
        final Object[] items = this.items;
        @SuppressWarnings("unchecked")
        E x = (E) items[takeIndex];
        items[takeIndex] = null;
        if (++takeIndex == items.length)
            takeIndex = 0;
        count--;
        if (itrs != null)
            itrs.elementDequeued();
        // 将线程从notFull.await()唤醒
        notFull.signal();
        return x;
    }

放入元素

    public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
            	// 等待take()方法的notFull.signal()
                notFull.await();
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }
    // 入队
    private void enqueue(E x) {
        // assert lock.getHoldCount() == 1;
        // assert items[putIndex] == null;
        final Object[] items = this.items;
        items[putIndex] = x;
        if (++putIndex == items.length)
            putIndex = 0;
        count++;
        // 唤醒put()里notEmpty.await()中的线程
        notEmpty.signal();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值