首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

堵塞队列之LinkedBlockingQueue 源码

2012-12-15 
阻塞队列之LinkedBlockingQueue 源码??package java.util.concurrentimport java.util.concurrent.atomic

阻塞队列之LinkedBlockingQueue 源码

?

?

package java.util.concurrent;

import java.util.concurrent.atomic.*;

import java.util.concurrent.locks.*;

import java.util.*;

?

?* @since 1.5

?* @author Doug Lea

?* @param <E> the type of elements held in this collection

?*

?*/

public class LinkedBlockingQueue<E> extends AbstractQueue<E>

? ? ? ? implements BlockingQueue<E>, java.io.Serializable {

? ? private static final long serialVersionUID = -6903933977591709194L;

?

?

?

? ? /**

? ? ?* Linked list node class

? ? ?*/

? ? static class Node<E> {

? ? ? ? E item;

? ? ? ? /**

? ? ? ? ?* One of:

? ? ? ? ?* - the real successor Node

? ? ? ? ?* - this Node, meaning the successor is head.next

? ? ? ? ?* - null, meaning there is no successor (this is the last node)

? ? ? ? ?*/

?

? ? ? ? Node<E> next;

? ? ? ? Node(E x) { item = x; }

? ? }

?

? ? /** The capacity bound, or Integer.MAX_VALUE if none */

? ? private final int capacity;

?

? ? /** Current number of elements */

? ? private final AtomicInteger count = new AtomicInteger(0);

?

? ? /** Head of linked list */

? ? private transient Node<E> head;

?

? ? /** Tail of linked list */

? ? private transient Node<E> last;

?

? ? /** Lock held by take, poll, etc */

? ? private final ReentrantLock takeLock = new ReentrantLock();

?

? ? /** Wait queue for waiting takes */

? ? private final Condition notEmpty = takeLock.newCondition();

?

? ? /** Lock held by put, offer, etc */

? ? private final ReentrantLock putLock = new ReentrantLock();

?

? ? /** Wait queue for waiting puts */

? ? private final Condition notFull = putLock.newCondition();

?

? ? /**

? ? ?* Signals a waiting take. Called only from put/offer (which do not

? ? ?* otherwise ordinarily lock takeLock.)

? ? ?*/

? ? private void signalNotEmpty() {

? ? ? ? final ReentrantLock takeLock = this.takeLock;

? ? ? ? takeLock.lock();

? ? ? ? try {

? ? ? ? ? ? notEmpty.signal();

? ? ? ? } finally {

? ? ? ? ? ? takeLock.unlock();

? ? ? ? }

? ? }

?

? ? /**

? ? ?* Signals a waiting put. Called only from take/poll.

? ? ?*/

? ? private void signalNotFull() {

? ? ? ? final ReentrantLock putLock = this.putLock;

? ? ? ? putLock.lock();

? ? ? ? try {

? ? ? ? ? ? notFull.signal();

? ? ? ? } finally {

? ? ? ? ? ? putLock.unlock();

? ? ? ? }

? ? }

?

? ? /**

? ? ?*?

? ? ?* maintained by this queue. ?(In other words, this method must allocate

? ? ?* a new array). ?The caller is thus free to modify the returned array.

? ? ?*

? ? ?* <p>This method acts as bridge between array-based and collection-based

? ? ?* APIs.

? ? ?*

? ? ?* @return an array containing all of the elements in this queue

? ? ?*/

? ? public Object[] toArray() {

? ? ? ? fullyLock();

? ? ? ? try {

? ? ? ? ? ? int size = count.get();

? ? ? ? ? ? Object[] a = new Object[size];

? ? ? ? ? ? int k = 0;

? ? ? ? ? ? for (Node<E> p = head.next; p != null; p = p.next)

? ? ? ? ? ? ? ? a[k++] = p.item;

? ? ? ? ? ? return a;

? ? ? ? } finally {

? ? ? ? ? ? fullyUnlock();

? ? ? ? }

? ? }

?

? ? /**

? ? ?* Returns an array containing all of the elements in this queue, in

? ? ?* proper sequence; the runtime type of the returned array is that of

? ? ?* the specified array. ?If the queue 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 queue.

? ? ?*

? ? ?* <p>If this queue fits in the specified array with room to spare

? ? ?* (i.e., the array has more elements than this queue), the element in

? ? ?* the array immediately following the end of the queue is set to

? ? ?* <tt>null</tt>.

? ? ?*

? ? ?* <p>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.

? ? ?*

? ? ?* <p>Suppose <tt>x</tt> is a queue known to contain only strings.

? ? ?* The following code can be used to dump the queue into a newly

? ? ?* allocated array of <tt>String</tt>:

? ? ?*

? ? ?* <pre>

? ? ?* ? ? String[] y = x.toArray(new String[0]);</pre>

? ? ?*

? ? ?* Note that <tt>toArray(new Object[0])</tt> is identical in function to

? ? ?* <tt>toArray()</tt>.

? ? ?*

? ? ?* @param a the array into which the elements of the queue 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 queue

? ? ?* @throws ArrayStoreException if the runtime type of the specified array

? ? ?* ? ? ? ? is not a supertype of the runtime type of every element in

? ? ?* ? ? ? ? this queue

? ? ?* @throws NullPointerException if the specified array is null

? ? ?*/

? ? // @SuppressWarnings("unchecked")

? ? public <T> T[] toArray(T[] a) {

? ? ? ? fullyLock();

? ? ? ? try {

? ? ? ? ? ? int size = count.get();

? ? ? ? ? ? if (a.length < size)

? ? ? ? ? ? ? ? a = (T[])java.lang.reflect.Array.newInstance

? ? ? ? ? ? ? ? ? ? (a.getClass().getComponentType(), size);

?

? ? ? ? ? ? int k = 0;

? ? ? ? ? ? for (Node<E> p = head.next; p != null; p = p.next)

? ? ? ? ? ? ? ? a[k++] = (T)p.item;

? ? ? ? ? ? if (a.length > k)

? ? ? ? ? ? ? ? a[k] = null;

? ? ? ? ? ? return a;

? ? ? ? } finally {

? ? ? ? ? ? fullyUnlock();

? ? ? ? }

? ? }

?

? ? public String toString() {

? ? ? ? fullyLock();

? ? ? ? try {

? ? ? ? ? ? return super.toString();

? ? ? ? } finally {

? ? ? ? ? ? fullyUnlock();

? ? ? ? }

? ? }

?

? ? /**

? ? ?* Atomically removes all of the elements from this queue.

? ? ?* The queue will be empty after this call returns.

? ? ?*/

? ? public void clear() {

? ? ? ? fullyLock();

? ? ? ? try {

? ? ? ? ? ? for (Node<E> p, h = head; (p = h.next) != null; h = p) {

? ? ? ? ? ? ? ? h.next = h;

? ? ? ? ? ? ? ? p.item = null;

? ? ? ? ? ? }

? ? ? ? ? ? head = last;

? ? ? ? ? ? // assert head.item == null && head.next == null;

? ? ? ? ? ? if (count.getAndSet(0) == capacity)

? ? ? ? ? ? ? ? notFull.signal();

? ? ? ? } finally {

? ? ? ? ? ? fullyUnlock();

? ? ? ? }

? ? }

?

? ? /**

? ? ?* @throws UnsupportedOperationException {@inheritDoc}

? ? ?* @throws ClassCastException ? ? ? ? ? ?{@inheritDoc}

? ? ?* @throws NullPointerException ? ? ? ? ?{@inheritDoc}

? ? ?* @throws IllegalArgumentException ? ? ?{@inheritDoc}

? ? ?*/

? ? 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}

? ? ?*/

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

? ? ? ? if (c == null)

? ? ? ? ? ? throw new NullPointerException();

? ? ? ? if (c == this)

? ? ? ? ? ? throw new IllegalArgumentException();

? ? ? ? boolean signalNotFull = false;

? ? ? ? final ReentrantLock takeLock = this.takeLock;

? ? ? ? takeLock.lock();

? ? ? ? try {

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

? ? ? ? ? ? Node<E> h = head;

? ? ? ? ? ? int i = 0;

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? while (i < n) {

? ? ? ? ? ? ? ? ? ? Node<E> p = h.next;

? ? ? ? ? ? ? ? ? ? c.add(p.item);

? ? ? ? ? ? ? ? ? ? p.item = null;

? ? ? ? ? ? ? ? ? ? h.next = h;

? ? ? ? ? ? ? ? ? ? h = p;

? ? ? ? ? ? ? ? ? ? ++i;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? return n;

? ? ? ? ? ? } finally {

? ? ? ? ? ? ? ? // Restore invariants even if c.add() threw

? ? ? ? ? ? ? ? if (i > 0) {

? ? ? ? ? ? ? ? ? ? // assert h.item == null;

? ? ? ? ? ? ? ? ? ? head = h;

? ? ? ? ? ? ? ? ? ? signalNotFull = (count.getAndAdd(-i) == capacity);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? } finally {

? ? ? ? ? ? takeLock.unlock();

? ? ? ? ? ? if (signalNotFull)

? ? ? ? ? ? ? ? ?signalNotFull();

? ? ? ? }

? ? }

?

? ? /**

? ? ?* Returns an iterator over the elements in this queue in proper sequence.

? ? ?* The returned <tt>Iterator</tt> is a "weakly consistent" iterator that

? ? ?* will never throw {@link ConcurrentModificationException},

? ? ?* and guarantees to traverse elements as they existed upon

? ? ?* construction of the iterator, and may (but is not guaranteed to)

? ? ?* reflect any modifications subsequent to construction.

? ? ?*

? ? ?* @return an iterator over the elements in this queue in proper sequence

? ? ?*/

? ? public Iterator<E> iterator() {

? ? ? return new Itr();

? ? }

?

? ? private class Itr implements Iterator<E> {

? ? ? ? /*

? ? ? ? ?* Basic weakly-consistent iterator. ?At all times hold the next

? ? ? ? ?* item to hand out so that if hasNext() reports true, we will

? ? ? ? ?* still have it to return even if lost race with a take etc.

? ? ? ? ?*/

? ? ? ? private Node<E> current;

? ? ? ? private Node<E> lastRet;

? ? ? ? private E currentElement;

?

? ? ? ? Itr() {

? ? ? ? ? ? fullyLock();

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? current = head.next;

? ? ? ? ? ? ? ? if (current != null)

? ? ? ? ? ? ? ? ? ? currentElement = current.item;

? ? ? ? ? ? } finally {

? ? ? ? ? ? ? ?fullyUnlock();

? ? ? ? ? ? }

? ? ? ? }

?

? ? ? ? public boolean hasNext() {

? ? ? ? ? ? return current != null;

? ? ? ? }

?

? ? ? ? /**

? ? ? ? ?* Returns the next live successor of p, or null if no such.

? ? ? ? ?* ?

? ? ? ? ?* Unlike other traversal methods, iterators need to handle both:

? ? ? ? ?* - dequeued nodes (p.next == p)

? ? ? ? ?* - ?(possibly multiple) interior removed nodes (p.item == null)

? ? ? ? ?*/

? ? ? ? private Node<E> nextNode(Node<E> p) {

? ? ? ? ? ? for (; ;) { ??

? ? ? ? ? ? ? ? Node s = p.next;

? ? ? ? ? ? ? ? if (s == p)

? ? ? ? ? ? ? ? ? ?return head.next;

? ? ? ? ? ? ? ? if (s == null || s.item != null)

? ? ? ? ? ? ? ? ? ?return s;

? ? ? ? ? ? ? ? p = s;

? ? ? ? ? ? }

? ? ? ? }

?

? ? ? ? public E next() {

? ? ? ? ? ? fullyLock();

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? if (current == null)

? ? ? ? ? ? ? ? ? ? throw new NoSuchElementException();

? ? ? ? ? ? ? ? E x = currentElement;

? ? ? ? ? ? ? ? lastRet = current;

? ? ? ? ? ? ? ? current = nextNode(current);

? ? ? ? ? ? ? ? currentElement = (current == null) ? null : current.item;

? ? ? ? ? ? ? ? return x;

? ? ? ? ? ? } finally {

? ? ? ? ? ? ? ?fullyUnlock();

? ? ? ? ? ? }

? ? ? ? }

?

? ? ? ? public void remove() {

? ? ? ? ? ? if (lastRet == null)

? ? ? ? ? ? ? ? throw new IllegalStateException();

? ? ? ? ? ? fullyLock();

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? Node<E> node = lastRet;

? ? ? ? ? ? ? ? lastRet = null;

? ? ? ? ? ? ? ? for (Node<E> trail = head, p = trail.next;

? ? ? ? ? ? ? ? ? ? ?p != null;

? ? ? ? ? ? ? ? ? ? ?trail = p, p = p.next) {

? ? ? ? ? ? ? ? ? ? ?if (p == node) {

? ? ? ? ? ? ? ? ? ? ? ? ?unlink(p, trail);

? ? ? ? ? ? ? ? ? ? ? ? ?break;

? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ?}

? ? ? ? ? ? } finally {

? ? ? ? ? ? ? ? fullyUnlock();

? ? ? ? ? ? }

? ? ? ? }

? ? }

?

? ? /**

? ? ?* Save the state to a stream (that is, serialize it).

? ? ?*

? ? ?* @serialData The capacity is emitted (int), followed by all of

? ? ?* its elements (each an <tt>Object</tt>) in the proper order,

? ? ?* followed by a null

? ? ?* @param s the stream

? ? ?*/

? ? private void writeObject(java.io.ObjectOutputStream s)

? ? ? ? throws java.io.IOException {

?

? ? ? ? fullyLock();

? ? ? ? try {

? ? ? ? ? ? // Write out any hidden stuff, plus capacity

? ? ? ? ? ? s.defaultWriteObject();

?

? ? ? ? ? ? // Write out all elements in the proper order.

? ? ? ? ? ? for (Node<E> p = head.next; p != null; p = p.next)

? ? ? ? ? ? ? ? s.writeObject(p.item);

?

? ? ? ? ? ? // Use trailing null as sentinel

? ? ? ? ? ? s.writeObject(null);

? ? ? ? } finally {

? ? ? ? ? ? fullyUnlock();

? ? ? ? }

? ? }

?

? ? /**

? ? ?* Reconstitute this queue instance from a stream (that is,

? ? ?* deserialize it).

? ? ?* @param s the stream

? ? ?*/

? ? private void readObject(java.io.ObjectInputStream s)

? ? ? ? throws java.io.IOException, ClassNotFoundException {

? ? ? ? // Read in capacity, and any hidden stuff

? ? ? ? s.defaultReadObject();

?

? ? ? ? count.set(0);

? ? ? ? last = head = new Node<E>(null);

?

? ? ? ? // Read in all elements and place in queue

? ? ? ? for (;;) {

? ? ? ? ? ? // @SuppressWarnings("unchecked")

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

? ? ? ? ? ? if (item == null)

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? add(item);

? ? ? ? }

? ? }

}


?

热点排行