LinkedBlockingDeque 源码分析

package source.java.util.concurrent;

import java.util.AbstractQueue;

import java.util.Collection;

import java.util.Iterator;

import java.util.NoSuchElementException;

import java.util.Objects;

import java.util.Spliterator;

import java.util.Spliterators;

import java.util.concurrent.BlockingDeque;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.ReentrantLock;

import java.util.function.Consumer;

import java.util.function.Predicate;

import com.sun.deploy.ref.Helpers;

/**

  • LinkedBlockingDeque 是基于链表实现的,可以选择有界或无界的双端阻塞队列。

    */

    public class LinkedBlockingDeque

    private static final long serialVersionUID = -387911632671998426L;

    /** 双向链表节点 */

    static final class Node

     /**
      * One of:
      * - the real predecessor Node
      * - this Node, meaning the predecessor is tail
      * - null, meaning there is no predecessor
      */
     Node<E> prev;
    
     /**
      * One of:
      * - the real successor Node
      * - this Node, meaning the successor is head
      * - null, meaning there is no successor
      */
     Node<E> next;
    
     Node(E x) {
         item = x;
     }

    }

    /**

    • 头结点
    • Invariant: (first == null && last == null) ||
    •        (first.prev == null && first.item != null)

      */

      transient Node

    /**

    • 尾节点
    • Invariant: (first == null && last == null) ||
    •        (last.next == null && last.item != null)

      */

      transient Node

    /** 双端队列中的元素总数 */

    private transient int count;

    /** 双端队列的容量 */

    private final int capacity;

    /** 控制访问的锁 */

    final ReentrantLock lock = new ReentrantLock();

    /** 队列为空时,用于阻塞执行 take 操作的线程的非空条件 */

    private final Condition notEmpty = lock.newCondition();

    /** 队列已满时,用于阻塞执行 put 操作的线程的非满条件 */

    private final Condition notFull = lock.newCondition();

    /**

    • 创建一个容量为 Integer.MAX_VALUE 的双端阻塞队列

      */

      public LinkedBlockingDeque() {

      this(Integer.MAX_VALUE);

      }

    /**

    • 创建一个容量为 capacity 的双端阻塞队列

      */

      public LinkedBlockingDeque(int capacity) {

      if (capacity <= 0) {

      throw new IllegalArgumentException();

      }

      this.capacity = capacity;

      }

    /**

    • Creates a {@code LinkedBlockingDeque} with a capacity of
    • {@link Integer#MAX_VALUE}, initially containing the elements of
    • the given collection, added in traversal order of the
    • collection‘s iterator.
    • @param c the collection of elements to initially contain
    • @throws NullPointerException if the specified collection or any
    •     of its elements are null

      */

      public LinkedBlockingDeque(Collection<? extends E> c) {

      this(Integer.MAX_VALUE);

      addAll(c);

      }

    private boolean linkFirst(Node

    private boolean linkLast(Node

    /**

    • Removes and returns first element, or null if empty.

      */

      private E unlinkFirst() {

      // assert lock.isHeldByCurrentThread();

      final Node

    /**

    • Removes and returns last element, or null if empty.

      */

      private E unlinkLast() {

      // assert lock.isHeldByCurrentThread();

      final Node

    /**

    • Unlinks x.

      */

      void unlink(Node

    // BlockingDeque methods

    /**

    • @throws IllegalStateException if this deque is full
    • @throws NullPointerException {@inheritDoc}

      */

      @Override

      public void addFirst(E e) {

      if (!offerFirst(e)) {

      throw new IllegalStateException("Deque full");

      }

      }

    /**

    • @throws IllegalStateException if this deque is full
    • @throws NullPointerException {@inheritDoc}

      */

      @Override

      public void addLast(E e) {

      if (!offerLast(e)) {

      throw new IllegalStateException("Deque full");

      }

      }

    /**

    • 如果队列已满,则直接返回 false,否则将目标元素 e 添加到队列头部

      */

      @Override

      public boolean offerFirst(E e) {

      if (e == null) {

      throw new NullPointerException();

      }

      final Node

    /**

    • 如果队列已满,则直接返回 false,否则将目标元素 e 添加到队列尾部

      */

      @Override

      public boolean offerLast(E e) {

      if (e == null) {

      throw new NullPointerException();

      }

      final Node

    /**

    • 将目标元素 e 添加到队列头部,如果队列已满,则阻塞等待有可用空间后重试

      */

      @Override

      public void putFirst(E e) throws InterruptedException {

      if (e == null) {

      throw new NullPointerException();

      }

      final Node

    /**

    • 将目标元素 e 添加到队列尾部,如果队列已满,则阻塞等待有可用空间后重试

      */

      @Override

      public void putLast(E e) throws InterruptedException {

      if (e == null) {

      throw new NullPointerException();

      }

      final Node

    /**

    • 在指定的超时时间内尝试将目标元素 e 添加到队列头部,成功则返回 true

      */

      @Override

      public boolean offerFirst(E e, long timeout, TimeUnit unit)

      throws InterruptedException {

      if (e == null) {

      throw new NullPointerException();

      }

      final Node

    /**

    • 在指定的超时时间内尝试将目标元素 e 添加到队列尾部,成功则返回 true

      */

      @Override

      public boolean offerLast(E e, long timeout, TimeUnit unit)

      throws InterruptedException {

      if (e == null) {

      throw new NullPointerException();

      }

      final Node

    /**

    • @throws NoSuchElementException {@inheritDoc}

      */

      @Override

      public E removeFirst() {

      final E x = pollFirst();

      if (x == null) {

      throw new NoSuchElementException();

      }

      return x;

      }

    /**

    • @throws NoSuchElementException {@inheritDoc}

      */

      @Override

      public E removeLast() {

      final E x = pollLast();

      if (x == null) {

      throw new NoSuchElementException();

      }

      return x;

      }

    /**

    • 如果队列为空,则立即返回 null,否则移除并返回头部元素
    • created by ZXD at 6 Dec 2018 T 21:03:40
    • @return

      */

      @Override

      public E pollFirst() {

      final ReentrantLock lock = this.lock;

      lock.lock();

      try {

      return unlinkFirst();

      } finally {

      lock.unlock();

      }

      }

    /**

    • 如果队列为空,则立即返回 null,否则移除并返回尾部元素
    • created by ZXD at 6 Dec 2018 T 21:04:43
    • @return

      */

      @Override

      public E pollLast() {

      final ReentrantLock lock = this.lock;

      lock.lock();

      try {

      return unlinkLast();

      } finally {

      lock.unlock();

      }

      }

    /**

    • 移除并返回头部节点,如果队列为空,则阻塞等待有可用元素之后重试
    • created by ZXD at 6 Dec 2018 T 21:00:25
    • @return
    • @throws InterruptedException

      */

      @Override

      public E takeFirst() throws InterruptedException {

      final ReentrantLock lock = this.lock;

      lock.lock();

      try {

      E x;

      // 尝试移除并返回头部节点

      while ( (x = unlinkFirst()) == null) {

      // 队列为空,则阻塞等待有可用元素之后重试

      notEmpty.await();

      }

      return x;

      } finally {

      lock.unlock();

      }

      }

    /**

    • 移除并返回尾部节点,如果队列为空,则阻塞等待有可用元素之后重试
    • created by ZXD at 6 Dec 2018 T 21:02:04
    • @return
    • @throws InterruptedException

      */

      @Override

      public E takeLast() throws InterruptedException {

      final ReentrantLock lock = this.lock;

      lock.lock();

      try {

      E x;

      // 尝试移除并返回尾部节点

      while ( (x = unlinkLast()) == null) {

      // 队列为空,则阻塞等待有可用元素之后重试

      notEmpty.await();

      }

      return x;

      } finally {

      lock.unlock();

      }

      }

    /**

    • 在指定的超时时间内尝试移除并返回头部元素,如果已经超时,则返回 null
    • created by ZXD at 6 Dec 2018 T 21:05:21
    • @param timeout
    • @param unit
    • @return
    • @throws InterruptedException

      */

      @Override

      public E pollFirst(long timeout, TimeUnit unit)

      throws InterruptedException {

      long nanos = unit.toNanos(timeout);

      final ReentrantLock lock = this.lock;

      lock.lockInterruptibly();

      try {

      E x;

      // 尝试移除并返回头部元素

      while ( (x = unlinkFirst()) == null) {

      // 已经超时则返回 null

      if (nanos <= 0L) {

      return null;

      }

      // 当前线程在非空条件上阻塞等待,被唤醒后进行重试

      nanos = notEmpty.awaitNanos(nanos);

      }

      // 移除成功则直接返回头部元素

      return x;

      } finally {

      lock.unlock();

      }

      }

    /**

    • created by ZXD at 6 Dec 2018 T 21:08:24
    • @param timeout
    • @param unit
    • @return
    • @throws InterruptedException

      */

      @Override

      public E pollLast(long timeout, TimeUnit unit)

      throws InterruptedException {

      long nanos = unit.toNanos(timeout);

      final ReentrantLock lock = this.lock;

      lock.lockInterruptibly();

      try {

      E x;

      // 尝试移除并返回尾部元素

      while ( (x = unlinkLast()) == null) {

      // 已经超时则返回 null

      if (nanos <= 0L) {

      return null;

      }

      // 当前线程在非空条件上阻塞等待,被唤醒后进行重试

      nanos = notEmpty.awaitNanos(nanos);

      }

      // 移除成功则直接返回尾部元素

      return x;

      } finally {

      lock.unlock();

      }

      }

    /**

    • @throws NoSuchElementException {@inheritDoc}

      */

      @Override

      public E getFirst() {

      final E x = peekFirst();

      if (x == null) {

      throw new NoSuchElementException();

      }

      return x;

      }

    /**

    • @throws NoSuchElementException {@inheritDoc}

      */

      @Override

      public E getLast() {

      final E x = peekLast();

      if (x == null) {

      throw new NoSuchElementException();

      }

      return x;

      }

    @Override

    public E peekFirst() {

    final ReentrantLock lock = this.lock;

    lock.lock();

    try {

    return first == null ? null : first.item;

    } finally {

    lock.unlock();

    }

    }

    @Override

    public E peekLast() {

    final ReentrantLock lock = this.lock;

    lock.lock();

    try {

    return last == null ? null : last.item;

    } finally {

    lock.unlock();

    }

    }

    @Override

    public boolean removeFirstOccurrence(Object o) {

    if (o == null) {

    return false;

    }

    final ReentrantLock lock = this.lock;

    lock.lock();

    try {

    for (Node

    @Override

    public boolean removeLastOccurrence(Object o) {

    if (o == null) {

    return false;

    }

    final ReentrantLock lock = this.lock;

    lock.lock();

    try {

    for (Node

    // BlockingQueue methods

    /**

    • Inserts the specified element at the end of this deque unless it would
    • violate capacity restrictions. When using a capacity-restricted deque,
    • it is generally preferable to use method {@link #offer(Object) offer}.
    • This method is equivalent to {@link #addLast}.
    • @throws IllegalStateException if this deque is full
    • @throws NullPointerException if the specified element is null

      */

      @Override

      public boolean add(E e) {

      addLast(e);

      return true;

      }

    /**

    • @throws NullPointerException if the specified element is null

      */

      @Override

      public boolean offer(E e) {

      return offerLast(e);

      }

    /**

    • @throws NullPointerException {@inheritDoc}
    • @throws InterruptedException {@inheritDoc}

      */

      @Override

      public void put(E e) throws InterruptedException {

      putLast(e);

      }

    /**

    • @throws NullPointerException {@inheritDoc}
    • @throws InterruptedException {@inheritDoc}

      */

      @Override

      public boolean offer(E e, long timeout, TimeUnit unit)

      throws InterruptedException {

      return offerLast(e, timeout, unit);

      }

    /**

    • Retrieves and removes the head of the queue represented by this deque.
    • This method differs from {@link #poll() poll()} only in that it throws an
    • exception if this deque is empty.
    • This method is equivalent to {@link #removeFirst() removeFirst}.
    • @return the head of the queue represented by this deque
    • @throws NoSuchElementException if this deque is empty

      */

      @Override

      public E remove() {

      return removeFirst();

      }

    @Override

    public E poll() {

    return pollFirst();

    }

    @Override

    public E take() throws InterruptedException {

    return takeFirst();

    }

    @Override

    public E poll(long timeout, TimeUnit unit) throws InterruptedException {

    return pollFirst(timeout, unit);

    }

    /**

    • Retrieves, but does not remove, the head of the queue represented by
    • this deque. This method differs from {@link #peek() peek()} only in that
    • it throws an exception if this deque is empty.
    • This method is equivalent to {@link #getFirst() getFirst}.
    • @return the head of the queue represented by this deque
    • @throws NoSuchElementException if this deque is empty

      */

      @Override

      public E element() {

      return getFirst();

      }

    @Override

    public E peek() {

    return peekFirst();

    }

    /**

    • Returns the number of additional elements that this deque can ideally
    • (in the absence of memory or resource constraints) accept without
    • blocking. This is always equal to the initial capacity of this deque
    • less the current {@code size} of this deque.
    • Note that you cannot always tell if an attempt to insert
    • an element will succeed by inspecting {@code remainingCapacity}
    • because it may be the case that another thread is about to
    • insert or remove an element.

      */

      @Override

      public int remainingCapacity() {

      final ReentrantLock lock = this.lock;

      lock.lock();

      try {

      return capacity - count;

      } finally {

      lock.unlock();

      }

      }

    /**

    • @throws UnsupportedOperationException {@inheritDoc}
    • @throws ClassCastException {@inheritDoc}
    • @throws NullPointerException {@inheritDoc}
    • @throws IllegalArgumentException {@inheritDoc}

      */

      @Override

      public int drainTo(Collection<? super E> c) {

      return drainTo(c, Integer.MAX_VALUE);

      }

    /**

    • @throws UnsupportedOperationException {@inheritDoc}
    • @throws ClassCastException {@inheritDoc}
    • @throws NullPointerException {@inheritDoc}
    • @throws IllegalArgumentException {@inheritDoc}

      */

      @Override

      public int drainTo(Collection<? super E> c, int maxElements) {

      Objects.requireNonNull(c);

      if (c == this) {

      throw new IllegalArgumentException();

      }

      if (maxElements <= 0) {

      return 0;

      }

      final ReentrantLock lock = this.lock;

      lock.lock();

      try {

      final int n = Math.min(maxElements, count);

      for (int i = 0; i < n; i++) {

      c.add(first.item); // In this order, in case add() throws.

      unlinkFirst();

      }

      return n;

      } finally {

      lock.unlock();

      }

      }

    // Stack methods

    /**

    • @throws IllegalStateException if this deque is full
    • @throws NullPointerException {@inheritDoc}

      */

      @Override

      public void push(E e) {

      addFirst(e);

      }

    /**

    • @throws NoSuchElementException {@inheritDoc}

      */

      @Override

      public E pop() {

      return removeFirst();

      }

    // Collection methods

    /**

    • Removes the first occurrence of the specified element from this deque.
    • If the deque does not contain the element, it is unchanged.
    • More formally, removes the first element {@code e} such that
    • {@code o.equals(e)} (if such an element exists).
    • Returns {@code true} if this deque contained the specified element
    • (or equivalently, if this deque changed as a result of the call).
    • This method is equivalent to
    • {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
    • @param o element to be removed from this deque, if present
    • @return {@code true} if this deque changed as a result of the call

      */

      @Override

      public boolean remove(Object o) {

      return removeFirstOccurrence(o);

      }

    /**

    • Returns the number of elements in this deque.
    • @return the number of elements in this deque

      */

      @Override

      public int size() {

      final ReentrantLock lock = this.lock;

      lock.lock();

      try {

      return count;

      } finally {

      lock.unlock();

      }

      }

    /**

    • Returns {@code true} if this deque contains the specified element.
    • More formally, returns {@code true} if and only if this deque contains
    • at least one element {@code e} such that {@code o.equals(e)}.
    • @param o object to be checked for containment in this deque
    • @return {@code true} if this deque contains the specified element

      */

      @Override

      public boolean contains(Object o) {

      if (o == null) {

      return false;

      }

      final ReentrantLock lock = this.lock;

      lock.lock();

      try {

      for (Node

    /**

    • Appends all of the elements in the specified collection to the end of
    • this deque, in the order that they are returned by the specified
    • collection‘s iterator. Attempts to {@code addAll} of a deque to
    • itself result in {@code IllegalArgumentException}.
    • @param c the elements to be inserted into this deque
    • @return {@code true} if this deque changed as a result of the call
    • @throws NullPointerException if the specified collection or any
    •     of its elements are null
    • @throws IllegalArgumentException if the collection is this deque
    • @throws IllegalStateException if this deque is full
    • @see #add(Object)

      */

      @Override

      public boolean addAll(Collection<? extends E> c) {

      if (c == this) {

      // As historically specified in AbstractQueue#addAll

      throw new IllegalArgumentException();

      }

      // Copy c into a private chain of Nodes

      Node

      // Atomically append the chain at the end

      final ReentrantLock lock = this.lock;

      lock.lock();

      try {

      if (count + n <= capacity) {

      beg.prev = last;

      if (first == null) {

      first = beg;

      } else {

      last.next = beg;

      }

      last = end;

      count += n;

      notEmpty.signalAll();

      return true;

      }

      } finally {

      lock.unlock();

      }

      // Fall back to historic non-atomic implementation, failing

      // with IllegalStateException when the capacity is exceeded.

      return super.addAll(c);

      }

    /**

    • Returns an array containing all of the elements in this deque, in
    • proper sequence (from first to last element).
    • The returned array will be "safe" in that no references to it are
    • maintained by this deque. (In other words, this method must allocate
    • a new array). The caller is thus free to modify the returned array.
    • This method acts as bridge between array-based and collection-based
    • APIs.
    • @return an array containing all of the elements in this deque

      */

      @Override

      @SuppressWarnings("unchecked")

      public Object[] toArray() {

      final ReentrantLock lock = this.lock;

      lock.lock();

      try {

      final Object[] a = new Object[count];

      int k = 0;

      for (Node

    /**

    • Returns an array containing all of the elements in this deque, in
    • proper sequence; the runtime type of the returned array is that of
    • the specified array. If the deque fits in the specified array, it
    • is returned therein. Otherwise, a new array is allocated with the
    • runtime type of the specified array and the size of this deque.
    • If this deque fits in the specified array with room to spare
    • (i.e., the array has more elements than this deque), the element in
    • the array immediately following the end of the deque is set to
    • {@code null}.
    • Like the {@link #toArray()} method, this method acts as bridge between
    • array-based and collection-based APIs. Further, this method allows
    • precise control over the runtime type of the output array, and may,
    • under certain circumstances, be used to save allocation costs.
    • Suppose {@code x} is a deque known to contain only strings.
    • The following code can be used to dump the deque into a newly
    • allocated array of {@code String}:
    •  {@code String[] y = x.toArray(new String[0]);}
    • Note that {@code toArray(new Object[0])} is identical in function to
    • {@code toArray()}.
    • @param a the array into which the elements of the deque are to
    •      be stored, if it is big enough; otherwise, a new array of the
    •      same runtime type is allocated for this purpose
    • @return an array containing all of the elements in this deque
    • @throws ArrayStoreException if the runtime type of the specified array
    •     is not a supertype of the runtime type of every element in
    •     this deque
    • @throws NullPointerException if the specified array is null

      */

      @Override

      @SuppressWarnings("unchecked")

      public

       int k = 0;
       for (Node<E> p = first; p != null; p = p.next) {
           a[k++] = (T)p.item;
       }
       if (a.length > k) {
           a[k] = null;
       }
       return a;

      } finally {

      lock.unlock();

      }

      }

    @Override

    public String toString() {

    return Helpers.collectionToString(this);

    }

    /**

    • Atomically removes all of the elements from this deque.
    • The deque will be empty after this call returns.

      */

      @Override

      public void clear() {

      final ReentrantLock lock = this.lock;

      lock.lock();

      try {

      for (Node

    /**

    • Used for any element traversal that is not entirely under lock.
    • Such traversals must handle both:
      • dequeued nodes (p.next == p)
      • (possibly multiple) interior removed nodes (p.item == null)

        */

        Node

    /**

    • Returns an iterator over the elements in this deque in proper sequence.
    • The elements will be returned in order from first (head) to last (tail).
    • The returned iterator is
    • weakly consistent.
    • @return an iterator over the elements in this deque in proper sequence

      */

      @Override

      public Iterator

    /**

    • Returns an iterator over the elements in this deque in reverse
    • sequential order. The elements will be returned in order from
    • last (tail) to first (head).
    • The returned iterator is
    • weakly consistent.
    • @return an iterator over the elements in this deque in reverse order

      */

      @Override

      public Iterator

    /**

    • Base class for LinkedBlockingDeque iterators.

      */

      private abstract class AbstractItr implements Iterator

    /** Forward iterator */

    private class Itr extends AbstractItr {

    Itr() {} // prevent access constructor creation

    @Override

    Node

    /** Descending iterator */

    private class DescendingItr extends AbstractItr {

    DescendingItr() {} // prevent access constructor creation

    @Override

    Node

    /**

    • A customized variant of Spliterators.IteratorSpliterator.
    • Keep this class in sync with (very similar) LBQSpliterator.

      */

      private final class LBDSpliterator implements Spliterator

      LBDSpliterator() {}

      @Override

      public long estimateSize() { return est; }

      @Override

      public Spliterator

      @Override

      public boolean tryAdvance(Consumer<? super E> action) {

      Objects.requireNonNull(action);

      if (!exhausted) {

      E e = null;

      final ReentrantLock lock = LinkedBlockingDeque.this.lock;

      lock.lock();

      try {

      Node

      @Override

      public void forEachRemaining(Consumer<? super E> action) {

      Objects.requireNonNull(action);

      if (!exhausted) {

      exhausted = true;

      final Node

      @Override

      public int characteristics() {

      return Spliterator.ORDERED |

      Spliterator.NONNULL |

      Spliterator.CONCURRENT;

      }

      }

    /**

    • Returns a {@link Spliterator} over the elements in this deque.
    • The returned spliterator is
    • weakly consistent.
    • The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
    • {@link Spliterator#ORDERED}, and {@link Spliterator#NONNULL}.
    • @implNote
    • The {@code Spliterator} implements {@code trySplit} to permit limited
    • parallelism.
    • @return a {@code Spliterator} over the elements in this deque
    • @since 1.8

      */

      @Override

      public Spliterator

    /**

    • @throws NullPointerException {@inheritDoc}

      */

      @Override

      public void forEach(Consumer<? super E> action) {

      Objects.requireNonNull(action);

      forEachFrom(action, null);

      }

    /**

    • Runs action on each element found during a traversal starting at p.
    • If p is null, traversal starts at head.

      */

      void forEachFrom(Consumer<? super E> action, Node

    /**

    • @throws NullPointerException {@inheritDoc}

      */

      @Override

      public boolean removeIf(Predicate<? super E> filter) {

      Objects.requireNonNull(filter);

      return bulkRemove(filter);

      }

    /**

    • @throws NullPointerException {@inheritDoc}

      */

      @Override

      public boolean removeAll(Collection<?> c) {

      Objects.requireNonNull(c);

      return bulkRemove(e -> c.contains(e));

      }

    /**

    • @throws NullPointerException {@inheritDoc}

      */

      @Override

      public boolean retainAll(Collection<?> c) {

      Objects.requireNonNull(c);

      return bulkRemove(e -> !c.contains(e));

      }

    /** Implementation of bulk remove methods. */

    @SuppressWarnings("unchecked")

    private boolean bulkRemove(Predicate<? super E> filter) {

    boolean removed = false;

    Node

         // 2. Run the filter on the elements while lock is free.
         for (int i = 0; i < n; i++) {
             final E e;
             if ((e = nodes[i].item) != null && filter.test(e)) {
                 deathRow |= 1L << i;
             }
         }
    
         // 3. Remove any filtered elements while holding the lock.
         if (deathRow != 0) {
             lock.lock();
             try {
                 for (int i = 0; i < n; i++) {
                     final Node<E> q;
                     if ((deathRow & 1L << i) != 0L
                             && (q = nodes[i]).item != null) {
                         unlink(q);
                         removed = true;
                     }
                 }
             } finally {
                 lock.unlock();
             }
         }
     } while (n > 0 && p != null);
     return removed;

    }

    /**

    • Saves this deque to a stream (that is, serializes it).
    • @param s the stream
    • @throws java.io.IOException if an I/O error occurs
    • @serialData The capacity (int), followed by elements (each an
    • {@code Object}) in the proper order, followed by a null

      */

      private void writeObject(java.io.ObjectOutputStream s)

      throws java.io.IOException {

      final ReentrantLock lock = this.lock;

      lock.lock();

      try {

      // Write out capacity and any hidden stuff

      s.defaultWriteObject();

      // Write out all elements in the proper order.

      for (Node

    /**

    • Reconstitutes this deque from a stream (that is, deserializes it).
    • @param s the stream
    • @throws ClassNotFoundException if the class of a serialized object
    •     could not be found
    • @throws java.io.IOException if an I/O error occurs

      */

      private void readObject(java.io.ObjectInputStream s)

      throws java.io.IOException, ClassNotFoundException {

      s.defaultReadObject();

      count = 0;

      first = null;

      last = null;

      // Read in all elements and place in queue

      for (;;) {

      @SuppressWarnings("unchecked")

      final E item = (E)s.readObject();

      if (item == null) {

      break;

      }

      add(item);

      }

      }

    void checkInvariants() {

    // assert lock.isHeldByCurrentThread();

    // Nodes may get self-linked or lose their item, but only

    // after being unlinked and becoming unreachable from first.

    for (Node

}

原文地址:https://www.cnblogs.com/zhuxudong/p/10079511.html

时间: 12-06

LinkedBlockingDeque 源码分析的相关文章

Spark源码分析之二:Job的调度模型与运行反馈

在<Spark源码分析之Job提交运行总流程概述>一文中,我们提到了,Job提交与运行的第一阶段Stage划分与提交,可以分为三个阶段: 1.Job的调度模型与运行反馈: 2.Stage划分: 3.Stage提交:对应TaskSet的生成. 今天,我们就结合源码来分析下第一个小阶段:Job的调度模型与运行反馈. 首先由DAGScheduler负责将Job提交到事件队列eventProcessLoop中,等待调度执行.入口方法为DAGScheduler的runJon()方法.代码如下: [jav

TeamTalk源码分析之login_server

login_server是TeamTalk的登录服务器,负责分配一个负载较小的MsgServer给客户端使用,按照新版TeamTalk完整部署教程来配置的话,login_server的服务端口就是8080,客户端登录服务器地址配置如下(这里是win版本客户端): 1.login_server启动流程 login_server的启动是从login_server.cpp中的main函数开始的,login_server.cpp所在工程路径为server\src\login_server.下表是logi

Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇)

1 背景 还记得前一篇<Android触摸屏事件派发机制详解与源码分析一(View篇)>中关于透过源码继续进阶实例验证模块中存在的点击Button却触发了LinearLayout的事件疑惑吗?当时说了,在那一篇咱们只讨论View的触摸事件派发机制,这个疑惑留在了这一篇解释,也就是ViewGroup的事件派发机制. PS:阅读本篇前建议先查看前一篇<Android触摸屏事件派发机制详解与源码分析一(View篇)>,这一篇承接上一篇. 关于View与ViewGroup的区别在前一篇的A

HashMap与TreeMap源码分析

1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Java这么久,也写过一些小项目,也使用过TreeMap无数次,但到现在才明白它的实现原理).因此本着"不要重复造轮子"的思想,就用这篇博客来记录分析TreeMap源码的过程,也顺便瞅一瞅HashMap. 2. 继承结构 (1) 继承结构 下面是HashMap与TreeMap的继承结构: pu

Linux内核源码分析--内核启动之(5)Image内核启动(rest_init函数)(Linux-3.0 ARMv7)【转】

原文地址:Linux内核源码分析--内核启动之(5)Image内核启动(rest_init函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://blog.chinaunix.net/uid-25909619-id-4938395.html 前面粗略分析start_kernel函数,此函数中基本上是对内存管理和各子系统的数据结构初始化.在内核初始化函数start_kernel执行到最后,就是调用rest_init函数,这个函数的主要使命就是创建并启动内核线

Spark的Master和Worker集群启动的源码分析

基于spark1.3.1的源码进行分析 spark master启动源码分析 1.在start-master.sh调用master的main方法,main方法调用 def main(argStrings: Array[String]) { SignalLogger.register(log) val conf = new SparkConf val args = new MasterArguments(argStrings, conf) val (actorSystem, _, _, _) =

Solr4.8.0源码分析(22)之 SolrCloud的Recovery策略(三)

Solr4.8.0源码分析(22)之 SolrCloud的Recovery策略(三) 本文是SolrCloud的Recovery策略系列的第三篇文章,前面两篇主要介绍了Recovery的总体流程,以及PeerSync策略.本文以及后续的文章将重点介绍Replication策略.Replication策略不但可以在SolrCloud中起到leader到replica的数据同步,也可以在用多个单独的Solr来实现主从同步.本文先介绍在SolrCloud的leader到replica的数据同步,下一篇

zg手册 之 python2.7.7源码分析(4)-- pyc字节码文件

什么是字节码 python解释器在执行python脚本文件时,对文件中的python源代码进行编译,编译的结果就是byte code(字节码) python虚拟机执行编译好的字节码,完成程序的运行 python会为导入的模块创建字节码文件 字节码文件的创建过程 当a.py依赖b.py时,如在a.py中import b python先检查是否有b.pyc文件(字节码文件),如果有,并且修改时间比b.py晚,就直接调用b.pyc 否则编译b.py生成b.pyc,然后加载新生成的字节码文件 字节码对象

LevelDB源码分析--Iterator

我们先来参考来至使用Iterator简化代码2-TwoLevelIterator的例子,略微修改希望能帮助更加容易立即,如果有不理解请各位看客阅读原文. 下面我们再来看一个例子,我们为一个书店写程序,书店里有许多书Book,每个书架(BookShelf)上有多本书. 类结构如下所示 class Book { private: string book_name_; }; class Shelf { private: vector<Book> books_; }; 如何遍历书架上所有的书呢?一种实

【Heritrix源码分析】Heritrix基本内容介绍

1.版本说明 (1)最新版本:3.3.0 (2)最新release版本:3.2.0 (3)重要历史版本:1.14.4 3.1.0及之前的版本:http://sourceforge.net/projects/archive-crawler/files/ 3.2.0及之后的版本:http://archive.org/ 由于国情需要,后者无法访问,因此本blog研究的是1.14.4版本. 2.官方材料 source:http://sourceforge.net/projects/archive-cra