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