FileDocCategorySizeDatePackage
LinkedBlockingDeque.javaAPI DocJava SE 6 API29690Tue Jun 10 00:25:56 BST 2008java.util.concurrent

LinkedBlockingDeque

public class LinkedBlockingDeque extends AbstractQueue implements BlockingDeque, Serializable
An optionally-bounded {@linkplain BlockingDeque blocking deque} based on linked nodes.

The optional capacity bound constructor argument serves as a way to prevent excessive expansion. The capacity, if unspecified, is equal to {@link Integer#MAX_VALUE}. Linked nodes are dynamically created upon each insertion unless this would bring the deque above capacity.

Most operations run in constant time (ignoring time spent blocking). Exceptions include {@link #remove(Object) remove}, {@link #removeFirstOccurrence removeFirstOccurrence}, {@link #removeLastOccurrence removeLastOccurrence}, {@link #contains contains}, {@link #iterator iterator.remove()}, and the bulk operations, all of which run in linear time.

This class and its iterator implement all of the optional methods of the {@link Collection} and {@link Iterator} interfaces.

This class is a member of the Java Collections Framework.

since
1.6
author
Doug Lea
param
the type of elements held in this collection

Fields Summary
private static final long
serialVersionUID
private transient Node
first
Pointer to first node
private transient Node
last
Pointer to last node
private transient int
count
Number of items in the deque
private final int
capacity
Maximum number of items in the deque
private final ReentrantLock
lock
Main lock guarding all access
private final Condition
notEmpty
Condition for waiting takes
private final Condition
notFull
Condition for waiting puts
Constructors Summary
public LinkedBlockingDeque()
Creates a LinkedBlockingDeque with a capacity of {@link Integer#MAX_VALUE}.


                  
      
        this(Integer.MAX_VALUE);
    
public LinkedBlockingDeque(int capacity)
Creates a LinkedBlockingDeque with the given (fixed) capacity.

param
capacity the capacity of this deque
throws
IllegalArgumentException if capacity is less than 1

        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
    
public LinkedBlockingDeque(Collection c)
Creates a 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

        this(Integer.MAX_VALUE);
        for (E e : c)
            add(e);
    
Methods Summary
public booleanadd(E e)
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 the element cannot be added at this time due to capacity restrictions
throws
NullPointerException if the specified element is null

	addLast(e);
	return true;
    
public voidaddFirst(E e)

throws
IllegalStateException {@inheritDoc}
throws
NullPointerException {@inheritDoc}

        if (!offerFirst(e))
            throw new IllegalStateException("Deque full");
    
public voidaddLast(E e)

throws
IllegalStateException {@inheritDoc}
throws
NullPointerException {@inheritDoc}

        if (!offerLast(e))
            throw new IllegalStateException("Deque full");
    
public voidclear()
Atomically removes all of the elements from this deque. The deque will be empty after this call returns.

        lock.lock();
        try {
            first = last = null;
            count = 0;
            notFull.signalAll();
        } finally {
            lock.unlock();
        }
    
public booleancontains(java.lang.Object o)
Returns true if this deque contains the specified element. More formally, returns true if and only if this deque contains at least one element e such that o.equals(e).

param
o object to be checked for containment in this deque
return
true if this deque contains the specified element

        if (o == null) return false;
        lock.lock();
        try {
            for (Node<E> p = first; p != null; p = p.next)
                if (o.equals(p.item))
                    return true;
            return false;
        } finally {
            lock.unlock();
        }
    
public java.util.IteratordescendingIterator()
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 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 new DescendingItr();
    
public intdrainTo(java.util.Collection c)

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

        if (c == null)
            throw new NullPointerException();
        if (c == this)
            throw new IllegalArgumentException();
        lock.lock();
        try {
            for (Node<E> p = first; p != null; p = p.next)
                c.add(p.item);
            int n = count;
            count = 0;
            first = last = null;
            notFull.signalAll();
            return n;
        } finally {
            lock.unlock();
        }
    
public intdrainTo(java.util.Collection c, int maxElements)

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

        if (c == null)
            throw new NullPointerException();
        if (c == this)
            throw new IllegalArgumentException();
        lock.lock();
        try {
            int n = 0;
            while (n < maxElements && first != null) {
                c.add(first.item);
                first.prev = null;
                first = first.next;
                --count;
                ++n;
            }
            if (first == null)
                last = null;
            notFull.signalAll();
            return n;
        } finally {
            lock.unlock();
        }
    
public Eelement()
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

	return getFirst();
    
public EgetFirst()

throws
NoSuchElementException {@inheritDoc}

        E x = peekFirst();
        if (x == null) throw new NoSuchElementException();
        return x;
    
public EgetLast()

throws
NoSuchElementException {@inheritDoc}

        E x = peekLast();
        if (x == null) throw new NoSuchElementException();
        return x;
    
public java.util.Iteratoriterator()
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 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 deque in proper sequence

        return new Itr();
    
private booleanlinkFirst(E e)
Links e as first element, or returns false if full.

        if (count >= capacity)
            return false;
        ++count;
        Node<E> f = first;
        Node<E> x = new Node<E>(e, null, f);
        first = x;
        if (last == null)
            last = x;
        else
            f.prev = x;
        notEmpty.signal();
        return true;
    
private booleanlinkLast(E e)
Links e as last element, or returns false if full.

        if (count >= capacity)
            return false;
        ++count;
        Node<E> l = last;
        Node<E> x = new Node<E>(e, l, null);
        last = x;
        if (first == null)
            first = x;
        else
            l.next = x;
        notEmpty.signal();
        return true;
    
public booleanoffer(E e)

throws
NullPointerException if the specified element is null

	return offerLast(e);
    
public booleanoffer(E e, long timeout, java.util.concurrent.TimeUnit unit)

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

	return offerLast(e, timeout, unit);
    
public booleanofferFirst(E e)

throws
NullPointerException {@inheritDoc}

        if (e == null) throw new NullPointerException();
        lock.lock();
        try {
            return linkFirst(e);
        } finally {
            lock.unlock();
        }
    
public booleanofferFirst(E e, long timeout, java.util.concurrent.TimeUnit unit)

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

        if (e == null) throw new NullPointerException();
	long nanos = unit.toNanos(timeout);
        lock.lockInterruptibly();
        try {
            for (;;) {
                if (linkFirst(e))
                    return true;
                if (nanos <= 0)
                    return false;
                nanos = notFull.awaitNanos(nanos);
            }
        } finally {
            lock.unlock();
        }
    
public booleanofferLast(E e)

throws
NullPointerException {@inheritDoc}

        if (e == null) throw new NullPointerException();
        lock.lock();
        try {
            return linkLast(e);
        } finally {
            lock.unlock();
        }
    
public booleanofferLast(E e, long timeout, java.util.concurrent.TimeUnit unit)

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

        if (e == null) throw new NullPointerException();
	long nanos = unit.toNanos(timeout);
        lock.lockInterruptibly();
        try {
            for (;;) {
                if (linkLast(e))
                    return true;
                if (nanos <= 0)
                    return false;
                nanos = notFull.awaitNanos(nanos);
            }
        } finally {
            lock.unlock();
        }
    
public Epeek()

	return peekFirst();
    
public EpeekFirst()

        lock.lock();
        try {
            return (first == null) ? null : first.item;
        } finally {
            lock.unlock();
        }
    
public EpeekLast()

        lock.lock();
        try {
            return (last == null) ? null : last.item;
        } finally {
            lock.unlock();
        }
    
public Epoll()

	return pollFirst();
    
public Epoll(long timeout, java.util.concurrent.TimeUnit unit)

	return pollFirst(timeout, unit);
    
public EpollFirst()

        lock.lock();
        try {
            return unlinkFirst();
        } finally {
            lock.unlock();
        }
    
public EpollFirst(long timeout, java.util.concurrent.TimeUnit unit)

	long nanos = unit.toNanos(timeout);
        lock.lockInterruptibly();
        try {
            for (;;) {
                E x = unlinkFirst();
                if (x != null)
                    return x;
                if (nanos <= 0)
                    return null;
                nanos = notEmpty.awaitNanos(nanos);
            }
        } finally {
            lock.unlock();
        }
    
public EpollLast()

        lock.lock();
        try {
            return unlinkLast();
        } finally {
            lock.unlock();
        }
    
public EpollLast(long timeout, java.util.concurrent.TimeUnit unit)

	long nanos = unit.toNanos(timeout);
        lock.lockInterruptibly();
        try {
            for (;;) {
                E x = unlinkLast();
                if (x != null)
                    return x;
                if (nanos <= 0)
                    return null;
                nanos = notEmpty.awaitNanos(nanos);
            }
        } finally {
            lock.unlock();
        }
    
public Epop()

throws
NoSuchElementException {@inheritDoc}

	return removeFirst();
    
public voidpush(E e)

throws
IllegalStateException {@inheritDoc}
throws
NullPointerException {@inheritDoc}

	addFirst(e);
    
public voidput(E e)

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

	putLast(e);
    
public voidputFirst(E e)

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

        if (e == null) throw new NullPointerException();
        lock.lock();
        try {
            while (!linkFirst(e))
                notFull.await();
        } finally {
            lock.unlock();
        }
    
public voidputLast(E e)

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

        if (e == null) throw new NullPointerException();
        lock.lock();
        try {
            while (!linkLast(e))
                notFull.await();
        } finally {
            lock.unlock();
        }
    
private voidreadObject(java.io.ObjectInputStream s)
Reconstitute this deque from a stream (that is, deserialize it).

param
s the stream

        s.defaultReadObject();
        count = 0;
        first = null;
        last = null;
        // Read in all elements and place in queue
        for (;;) {
            E item = (E)s.readObject();
            if (item == null)
                break;
            add(item);
        }
    
public intremainingCapacity()
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 size of this deque.

Note that you cannot always tell if an attempt to insert an element will succeed by inspecting remainingCapacity because it may be the case that another thread is about to insert or remove an element.

        lock.lock();
        try {
            return capacity - count;
        } finally {
            lock.unlock();
        }
    
public Eremove()
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

	return removeFirst();
    
public booleanremove(java.lang.Object o)
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 e such that o.equals(e) (if such an element exists). Returns 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
true if this deque changed as a result of the call

	return removeFirstOccurrence(o);
    
public EremoveFirst()

throws
NoSuchElementException {@inheritDoc}

        E x = pollFirst();
        if (x == null) throw new NoSuchElementException();
        return x;
    
public booleanremoveFirstOccurrence(java.lang.Object o)

        if (o == null) return false;
        lock.lock();
        try {
            for (Node<E> p = first; p != null; p = p.next) {
                if (o.equals(p.item)) {
                    unlink(p);
                    return true;
                }
            }
            return false;
        } finally {
            lock.unlock();
        }
    
public EremoveLast()

throws
NoSuchElementException {@inheritDoc}

        E x = pollLast();
        if (x == null) throw new NoSuchElementException();
        return x;
    
public booleanremoveLastOccurrence(java.lang.Object o)

        if (o == null) return false;
        lock.lock();
        try {
            for (Node<E> p = last; p != null; p = p.prev) {
                if (o.equals(p.item)) {
                    unlink(p);
                    return true;
                }
            }
            return false;
        } finally {
            lock.unlock();
        }
    
booleanremoveNode(java.util.concurrent.LinkedBlockingDeque$Node e)
Variant of removeFirstOccurrence needed by iterator.remove. Searches for the node, not its contents.

        lock.lock();
        try {
            for (Node<E> p = first; p != null; p = p.next) {
                if (p == e) {
                    unlink(p);
                    return true;
                }
            }
            return false;
        } finally {
            lock.unlock();
        }
    
public intsize()
Returns the number of elements in this deque.

return
the number of elements in this deque

        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    
public Etake()

	return takeFirst();
    
public EtakeFirst()

        lock.lock();
        try {
            E x;
            while ( (x = unlinkFirst()) == null)
                notEmpty.await();
            return x;
        } finally {
            lock.unlock();
        }
    
public EtakeLast()

        lock.lock();
        try {
            E x;
            while ( (x = unlinkLast()) == null)
                notEmpty.await();
            return x;
        } finally {
            lock.unlock();
        }
    
public java.lang.Object[]toArray()
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

        lock.lock();
        try {
            Object[] a = new Object[count];
            int k = 0;
            for (Node<E> p = first; p != null; p = p.next)
                a[k++] = p.item;
            return a;
        } finally {
            lock.unlock();
        }
    
public T[]toArray(T[] a)
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 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 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 String:

String[] y = x.toArray(new String[0]);
Note that toArray(new Object[0]) is identical in function to 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

        lock.lock();
        try {
            if (a.length < count)
                a = (T[])java.lang.reflect.Array.newInstance(
                    a.getClass().getComponentType(),
                    count
                    );

            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();
        }
    
public java.lang.StringtoString()

        lock.lock();
        try {
            return super.toString();
        } finally {
            lock.unlock();
        }
    
private voidunlink(java.util.concurrent.LinkedBlockingDeque$Node x)
Unlink e

        Node<E> p = x.prev;
        Node<E> n = x.next;
        if (p == null) {
            if (n == null)
                first = last = null;
            else {
                n.prev = null;
                first = n;
            }
        } else if (n == null) {
            p.next = null;
            last = p;
        } else {
            p.next = n;
            n.prev = p;
        }
        --count;
        notFull.signalAll();
    
private EunlinkFirst()
Removes and returns first element, or null if empty.

        Node<E> f = first;
        if (f == null)
            return null;
        Node<E> n = f.next;
        first = n;
        if (n == null)
            last = null;
        else
            n.prev = null;
        --count;
        notFull.signal();
        return f.item;
    
private EunlinkLast()
Removes and returns last element, or null if empty.

        Node<E> l = last;
        if (l == null)
            return null;
        Node<E> p = l.prev;
        last = p;
        if (p == null)
            first = null;
        else
            p.next = null;
        --count;
        notFull.signal();
        return l.item;
    
private voidwriteObject(java.io.ObjectOutputStream s)
Save the state of this deque to a stream (that is, serialize it).

serialData
The capacity (int), followed by elements (each an Object) in the proper order, followed by a null
param
s the stream

        lock.lock();
        try {
            // Write out capacity and any hidden stuff
            s.defaultWriteObject();
            // Write out all elements in the proper order.
            for (Node<E> p = first; p != null; p = p.next)
                s.writeObject(p.item);
            // Use trailing null as sentinel
            s.writeObject(null);
        } finally {
            lock.unlock();
        }