linkedblockingdeque.java
来自「SRI international 发布的OAA框架软件」· Java 代码 · 共 772 行 · 第 1/2 页
JAVA
772 行
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/licenses/publicdomain
*/
package edu.emory.mathcs.backport.java.util.concurrent;
import java.util.*;
import edu.emory.mathcs.backport.java.util.AbstractQueue;
import edu.emory.mathcs.backport.java.util.concurrent.helpers.*;
import edu.emory.mathcs.backport.java.util.concurrent.locks.*;
/**
* An optionally-bounded {@linkplain BlockingDeque blocking deque} based on
* linked nodes.
*
* <p> 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.
*
* <p>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.
*
* <p>This class and its iterator implement all of the
* <em>optional</em> methods of the {@link Collection} and {@link
* Iterator} interfaces. This class is a member of the <a
* href="{@docRoot}/../guide/collections/index.html"> Java Collections
* Framework</a>.
*
* @since 1.6
* @author Doug Lea
*/
public class LinkedBlockingDeque
extends AbstractQueue
implements BlockingDeque, java.io.Serializable {
/*
* Implemented as a simple doubly-linked list protected by a
* single lock and using conditions to manage blocking.
*/
private static final long serialVersionUID = -387911632671998426L;
/** Doubly-linked list node class */
static final class Node {
Object item;
Node prev;
Node next;
Node(Object x, Node p, Node n) {
item = x;
prev = p;
next = n;
}
}
/** Pointer to first node */
private transient Node first;
/** Pointer to last node */
private transient Node last;
/** Number of items in the deque */
private transient int count;
/** Maximum number of items in the deque */
private final int capacity;
/** Main lock guarding all access */
private final ReentrantLock lock = new ReentrantLock();
/** Condition for waiting takes */
private final Condition notEmpty = lock.newCondition();
/** Condition for waiting puts */
private final Condition notFull = lock.newCondition();
/**
* Creates a <tt>LinkedBlockingDeque</tt> with a capacity of
* {@link Integer#MAX_VALUE}.
*/
public LinkedBlockingDeque() {
this(Integer.MAX_VALUE);
}
/**
* Creates a <tt>LinkedBlockingDeque</tt> with the given (fixed)
* capacity.
* @param capacity the capacity of this deque
* @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
*/
public LinkedBlockingDeque(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
}
/**
* Creates a <tt>LinkedBlockingDeque</tt> 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 <tt>c</tt> or any element within it
* is <tt>null</tt>
*/
public LinkedBlockingDeque(Collection c) {
this(Integer.MAX_VALUE);
for (Iterator itr = c.iterator(); itr.hasNext();) {
Object e = itr.next();
add(e);
}
}
// Basic linking and unlinking operations, called only while holding lock
/**
* Link e as first element, or return false if full
*/
private boolean linkFirst(Object e) {
if (count >= capacity)
return false;
++count;
Node f = first;
Node x = new Node(e, null, f);
first = x;
if (last == null)
last = x;
else
f.prev = x;
notEmpty.signal();
return true;
}
/**
* Link e as last element, or return false if full
*/
private boolean linkLast(Object e) {
if (count >= capacity)
return false;
++count;
Node l = last;
Node x = new Node(e, l, null);
last = x;
if (first == null)
first = x;
else
l.next = x;
notEmpty.signal();
return true;
}
/**
* Remove and return first element, or null if empty
*/
private Object unlinkFirst() {
Node f = first;
if (f == null)
return null;
Node n = f.next;
first = n;
if (n == null)
last = null;
else
n.prev = null;
--count;
notFull.signal();
return f.item;
}
/**
* Remove and return last element, or null if empty
*/
private Object unlinkLast() {
Node l = last;
if (l == null)
return null;
Node p = l.prev;
last = p;
if (p == null)
first = null;
else
p.next = null;
--count;
notFull.signal();
return l.item;
}
/**
* Unlink e
*/
private void unlink(Node x) {
Node p = x.prev;
Node 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();
}
// Deque methods
public boolean offerFirst(Object o) {
if (o == null) throw new NullPointerException();
lock.lock();
try {
return linkFirst(o);
} finally {
lock.unlock();
}
}
public boolean offerLast(Object o) {
if (o == null) throw new NullPointerException();
lock.lock();
try {
return linkLast(o);
} finally {
lock.unlock();
}
}
public void addFirst(Object e) {
if (!offerFirst(e))
throw new IllegalStateException("Deque full");
}
public void addLast(Object e) {
if (!offerLast(e))
throw new IllegalStateException("Deque full");
}
public Object pollFirst() {
lock.lock();
try {
return unlinkFirst();
} finally {
lock.unlock();
}
}
public Object pollLast() {
lock.lock();
try {
return unlinkLast();
} finally {
lock.unlock();
}
}
public Object removeFirst() {
Object x = pollFirst();
if (x == null) throw new NoSuchElementException();
return x;
}
public Object removeLast() {
Object x = pollLast();
if (x == null) throw new NoSuchElementException();
return x;
}
public Object peekFirst() {
lock.lock();
try {
return (first == null) ? null : first.item;
} finally {
lock.unlock();
}
}
public Object peekLast() {
lock.lock();
try {
return (last == null) ? null : last.item;
} finally {
lock.unlock();
}
}
public Object getFirst() {
Object x = peekFirst();
if (x == null) throw new NoSuchElementException();
return x;
}
public Object getLast() {
Object x = peekLast();
if (x == null) throw new NoSuchElementException();
return x;
}
// BlockingDeque methods
public void putFirst(Object o) throws InterruptedException {
if (o == null) throw new NullPointerException();
lock.lock();
try {
while (!linkFirst(o))
notFull.await();
} finally {
lock.unlock();
}
}
public void putLast(Object o) throws InterruptedException {
if (o == null) throw new NullPointerException();
lock.lock();
try {
while (!linkLast(o))
notFull.await();
} finally {
lock.unlock();
}
}
public Object takeFirst() throws InterruptedException {
lock.lock();
try {
Object x;
while ( (x = unlinkFirst()) == null)
notEmpty.await();
return x;
} finally {
lock.unlock();
}
}
public Object takeLast() throws InterruptedException {
lock.lock();
try {
Object x;
while ( (x = unlinkLast()) == null)
notEmpty.await();
return x;
} finally {
lock.unlock();
}
}
public boolean offerFirst(Object o, long timeout, TimeUnit unit)
throws InterruptedException {
if (o == null) throw new NullPointerException();
lock.lockInterruptibly();
try {
long nanos = unit.toNanos(timeout);
long deadline = Utils.nanoTime() + nanos;
for (;;) {
if (linkFirst(o))
return true;
if (nanos <= 0)
return false;
notFull.await(nanos, TimeUnit.NANOSECONDS);
nanos = deadline - Utils.nanoTime();
}
} finally {
lock.unlock();
}
}
public boolean offerLast(Object o, long timeout, TimeUnit unit)
throws InterruptedException {
if (o == null) throw new NullPointerException();
lock.lockInterruptibly();
try {
long nanos = unit.toNanos(timeout);
long deadline = Utils.nanoTime() + nanos;
for (;;) {
if (linkLast(o))
return true;
if (nanos <= 0)
return false;
notFull.await(nanos, TimeUnit.NANOSECONDS);
nanos = deadline - Utils.nanoTime();
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?