/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add}) */ publicbooleanadd(E e){ final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); returntrue; } finally { lock.unlock(); } }
再来看看get()方法,源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/** * {@inheritDoc} * * @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index){ return get(getArray(), index); }
/** * Gets the array. Non-private so as to also be accessible * from CopyOnWriteArraySet class. */ final Object[] getArray() { return array; }
/** * Returns an iterator over the elements in this list in proper sequence. * * <p>The returned iterator provides a snapshot of the state of the list * when the iterator was constructed. No synchronization is needed while * traversing the iterator. The iterator does <em>NOT</em> support the * {@code remove} method. * * @return an iterator over the elements in this list in proper sequence */ public Iterator<E> iterator(){ returnnew COWIterator<E>(getArray(), 0); }
staticfinalclassCOWIterator<E> implementsListIterator<E> { /** Snapshot of the array */ privatefinal Object[] snapshot; /** Index of element to be returned by subsequent call to next. */ privateint cursor;
@SuppressWarnings("unchecked") public E next(){ if (! hasNext()) thrownew NoSuchElementException(); return (E) snapshot[cursor++]; }
@SuppressWarnings("unchecked") public E previous(){ if (! hasPrevious()) thrownew NoSuchElementException(); return (E) snapshot[--cursor]; }
publicintnextIndex(){ return cursor; }
publicintpreviousIndex(){ return cursor-1; }
/** * Not supported. Always throws UnsupportedOperationException. * @throws UnsupportedOperationException always; {@code remove} * is not supported by this iterator. */ publicvoidremove(){ thrownew UnsupportedOperationException(); }
/** * Not supported. Always throws UnsupportedOperationException. * @throws UnsupportedOperationException always; {@code set} * is not supported by this iterator. */ publicvoidset(E e){ thrownew UnsupportedOperationException(); }
/** * Not supported. Always throws UnsupportedOperationException. * @throws UnsupportedOperationException always; {@code add} * is not supported by this iterator. */ publicvoidadd(E e){ thrownew UnsupportedOperationException(); }
@Override publicvoidforEachRemaining(Consumer<? super E> action){ Objects.requireNonNull(action); Object[] elements = snapshot; finalint size = elements.length; for (int i = cursor; i < size; i++) { @SuppressWarnings("unchecked") E e = (E) elements[i]; action.accept(e); } cursor = size; } }
/** * Inserts the specified element at the tail of this queue, waiting * for space to become available if the queue is full. * * @throws InterruptedException {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ publicvoidput(E e)throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; // 阻塞过程中可以被中断 lock.lockInterruptibly(); try { // 队列满了的情况下,当前线程将会被notFull挂起加到等待队列中 while (count == items.length) notFull.await(); enqueue(e); } finally { lock.unlock(); } }
/** * Inserts the specified element at the tail of this queue, waiting if * necessary for space to become available. * * @throws InterruptedException {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ publicvoidput(E e)throws InterruptedException { if (e == null) thrownew NullPointerException(); // 队列临时容量缓存,作为执行唤醒/阻塞线程操作标记 int c = -1; Node<E> node = new Node<E>(e); final ReentrantLock putLock = this.putLock; // 队列元素个数 final AtomicInteger count = this.count; putLock.lockInterruptibly(); try { // 自旋排除硬件加锁延时问题 // 如果队列已满,线程阻塞等待 while (count.get() == capacity) { notFull.await(); } enqueue(node); // 原子操作 i++ c = count.getAndIncrement(); // 队列未满,仍可添加,唤醒等待的入列线程 if (c + 1 < capacity) notFull.signal(); } finally { putLock.unlock(); } // c == 0 说明队列为空,唤醒入列线程入列 if (c == 0) signalNotEmpty(); }