LinkedBlockingQueue 源码

  add        增加一个元索               如果队列已满,则抛出一个IIIegaISlabEepeplian异常
  remove     移除并返回队列头部的元素    如果队列为空,则抛出一个NoSuchElementException异常
  element    返回队列头部的元素          如果队列为空,则抛出一个NoSuchElementException异常
  offer      添加一个元素并返回true      如果队列已满,则返回false
  poll       移除并返问队列头部的元素    如果队列为空,则返回null
  peek       返回队列头部的元素          如果队列为空,则返回null
  put        添加一个元素                如果队列满,则阻塞
  take       移除并返回队列头部的元素     如果队列为空,则阻塞

capacity  容量
count 当前元素数
head 首节点
last 尾节点
takeLock take锁
notEmpty take锁上的条件
putLock put锁
notFull put锁上的条件

LinkedBlockingQueue() 无参构造,初始化容量为Integer的最大值。初始化队列首尾节点。
enqueue(Node<E> node) 元素进入队列,作为对尾。使用前需要首尾节点初始化。
LinkedBlockingQueue(Collection<? extends E> c)  构造器,调用一个参数构造器,获取put锁,遍历集合,如果存在元素为null抛出空指针异常,把集合元素添加到队尾。记录元素数量count。释放独占锁。

put 添加元素到队尾,如果队列满阻塞:如果元素是null,抛出空指针异常;获取put独占锁;自旋如果队列已满,则在put条件队列上等待;结束自旋后入队列;对当前元素数cas+1,如果+1后的值扔小于容量,则唤醒在put条件队列上等待的一个节点;释放put独占锁;最后如果添加元素前队列是空的    则获取take独占锁,唤醒在take条件队列上等待的一个节点,释放take独占锁。

take 队首移除元素,如果队列空阻塞:获取take独占锁;自旋 如果队列为空,在take条件队列上等待;结束自旋后队首元素出队列;cas对当前元素数-1,如果-1后元素数仍大于1,唤醒在take条件队列上等待的节点;释放take独占锁;最后如果出队列前队列已满,获取put独占锁,唤醒在put条件队列上等待的节点,释放put独占锁;返回元素。

原理:在队尾添加元素,如果队列满则阻塞:如果添加的元素是空,则抛出空指针异常;获取put独占锁;自旋如果队列已满,则在put条件队列上等待,直到被唤醒且队列不满结束自旋;结束自旋后,执行入队列操作;cas操作修改当前的元素数量+1,如果加1后仍没有达到队列容量则唤醒put条件队列上一个等待的节点,让它解除阻塞来获取元素;释放put独占锁;如果添加元素前队列是空的,则获取take独占锁,唤醒在take条件队列上等待的节点,告知他们可以获取元素了,不用等待了,释放put独占锁。在队首移除元素,如果队列空则阻塞:获取take独占锁;自旋如果队列为空则在take条件队列上等待,直到被唤醒;结束自旋后出队列;cas操作修改当前元素-1,如果减1前存在至少2个元素,则唤醒在take条件队列上等待的一个节点,让其来获取元素;释放take独占锁;如果移除元素前队列已满,则获取put独占锁,唤醒在put条件队列上等待的一个节点,告知其可以添加元素了,释放put独占锁,最后返回移除的元素。

猜你喜欢

转载自blog.csdn.net/liangwenmail/article/details/81636138