作 者:haifeiWu
原文链接:https://www.hchstudio.cn/article/2019/bf19/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
由于版权原因,请阅读原文 --> ArrayBlockingQueue 阻塞队列

作 者:haifeiWu
原文链接:https://www.hchstudio.cn/article/2019/bf19/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
作 者:haifeiWu
原文链接:https://www.hchstudio.cn/article/2019/bf19/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
一直都在写业务代码,对于 jdk 底层的代码难免有些疏忽,所以决定把一些比较重要的源码过一遍……
是什么?
ArrayBlockingQueue 是一个用数组实现的有界阻塞队列。此队列按照先进先出(FIFO)的原则对元素进行排序。默认情况下不保证访问者公平的访问队列,所谓公平访问队列是指阻塞的所有生产者线程或消费者线程,当队列可用时,可以按照阻塞的先后顺序访问队列,即先阻塞的生产者线程,可以先往队列里插入元素,先阻塞的消费者线程,可以先从队列里获取元素。通常情况下为了保证公平性会降低吞吐量。
主要源码实现
ArrayBlockingQueue 基于数组,代码相对简单,下面是主要的代码实现。
主要常量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| final Object[] items;
int takeIndex;
int putIndex;
int count;
final ReentrantLock lock;
private final Condition notEmpty;
private final Condition notFull;
|
主要方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
private void enqueue(E x) { final Object[] items = this.items; items[putIndex] = x; if (++putIndex == items.length) putIndex = 0; count++; notEmpty.signal(); }
private E dequeue() { 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.signal(); return x; }
void removeAt(final int removeIndex) { final Object[] items = this.items; if (removeIndex == takeIndex) { items[takeIndex] = null; if (++takeIndex == items.length) takeIndex = 0; count--; if (itrs != null) itrs.elementDequeued(); } else {
final int putIndex = this.putIndex; for (int i = removeIndex;;) { int next = i + 1; if (next == items.length) next = 0; if (next != putIndex) { items[i] = items[next]; i = next; } else { items[i] = null; this.putIndex = i; break; } } count--; if (itrs != null) itrs.removedAt(removeIndex); } notFull.signal(); }
public void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) notFull.await(); enqueue(e); } finally { lock.unlock(); } }
public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == 0) notEmpty.await(); return dequeue(); } finally { lock.unlock(); } }
|
基于 ArrayBlockingQueue 实现的生产者-消费者模型
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public static void main(String[] args) { final ArrayBlockingQueue<String> container = new ArrayBlockingQueue<>(10);
final int[] producerCount = {0}; new Thread(() -> { while (true) { try { System.out.println("我生产了一个 : " + producerCount[0]++); container.put(producerCount[0] + ""); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }).start();
new Thread(() -> { while (true) { try { System.out.println("我消费了一个 : " + container.take()); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }
|
小结
精诚所至,金石为开……

作 者:haifeiWu
原文链接:https://www.hchstudio.cn/article/2019/bf19/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。