ArrayBlockingQueue和LinkedBlockingQueue

1. ArrayBlockingQueue 数组存储,固定大小的队列。

一个items数组,一个putIndex指针,从0到len代表已经入队了多少个元素。一个takeIndex指针,从0到len代表出队的元素位置。一个count,记录当前队列里有多少元素。

putIndex指针入队的时候不断++,takeIndex出队的时候不断++。这个队列不是一个循环队列,判断队列空和满用count和items.length比较。

入队:

内部的lock锁定,如果队列满,sleep等待,当可以插入的时候,items[++putIndex]是插入元素,如果队列插入以后满了,通知出队的等待线程。

lock.lock()

while(count == items.length)

  lock.condition.await() //释放锁,并等待

items[++putIndex] = element

count++

lock.condition.signal()

lock.unlock()

出队:

内部的lock锁定,如果队列空,sleep等待,当可以出队的时候,items[++takeIndex]

lock.lock()

while(count == 0)

  lock.condition.await() //释放锁,并等待

element = items[++takeIndex]

count--

lock.condition.signal()

lock.unlock()

2. LinkedBlockingQueue 链表存储,默认是无限制的队列

区别于ArrayBlockingQueue使用数组存储,在存储上是没有限制的,不过也可以通过capacity,count配合锁来控制队列长度。

head,last 代表链表的头尾指针,用来入队和出队,在last位置入队,head位置出队。

takeLock和putLock来控制队列空和满时候的阻塞,这里对比ArrayBlockingQueue,出队和入队使用的是两把锁。

capacity,count来控制队列中元素的数量,因为是用的两个锁,所以count是AtomicInteger。

入队:

putLock.lock()

while (count == capacity)

  putLock.condition.await()

last = last.next = element

count++

if (count + 1<capacity) //因为入队的时候有可能出队了,所以需要再检查一下,不像ArrayBlockingQueue直接signal()

  putLock.condition.signal()

putLock.unlock()

出队:

takeLock.lock()

while (count == 0)

  takeLock.condition.await()

element = head

head = element.next

count--

if (count > 1) 

  takeLock.condition.signal()

takeLock.unlock()

 3. SynchronousQueue

生产者和消费者直接传递数据,不对数据做缓存。生产者和消费者通过在队列里排队的方式来阻塞和唤醒。

原文地址:https://www.cnblogs.com/23lalala/p/5213833.html