public class ArrayBlockingQueue
private static final long serialVersionUID = -817911632652898426L;
private final E[] items; /** The queued items */
private int takeIndex; /** items index for next take, poll or remove */
private int putIndex; /** items index for next put, offer, or add. */
private int count; /** Number of items in the queue */
/** Concurrency control uses the classic two-condition algorithm found in any textbook. */
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 */
}
|
public ArrayBlockingQueue(int capacity) {} //只有一个参数用来指定容量
public ArrayBlockingQueue(int capacity, boolean fair) {} / /指定容量和公平性
public ArrayBlockingQueue(int capacity, boolean fair, Collection extends E> c) {} //指定容量、公平性以及用另外一个集合进行初始化
|
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
final E[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
try {
while (count == items.length)
notFull.await();
} catch (InterruptedException ie) {
notFull.signal(); // propagate to non-interrupted thread
throw ie;
}
insert(e);
} finally {
lock.unlock();
}
}
|
从put方法的实现可以看出,它先获取了锁,并且获取的是可中断锁,然后判断当前元素个数是否等于数组的长度,如果相等,则调用notFull.await()进行等待,如果捕获到中断异常,则唤醒线程并抛出异常。
当被其他线程唤醒时,通过insert(e)方法插入元素,最后解锁。
|
private void insert(E x) {
items[putIndex] = x;
putIndex = inc(putIndex);
++count;
notEmpty.signal();
}
|
它是一个private方法,插入成功后,通过notEmpty唤醒正在等待取元素的线程。 |
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
try {
while (count == 0)
notEmpty.await();
} catch (InterruptedException ie) {
notEmpty.signal(); // propagate to non-interrupted thread
throw ie;
}
E x = extract();
return x;
} finally {
lock.unlock();
}
}
|
跟put方法实现很类似,
只不过put方法等待的是notFull信号,而take方法等待的是notEmpty信号。在take方法中,如果可以取元素,则通过extract方法取得元素,下面是extract方法的实现:
|
private E extract() {
final E[] items = this.items;
E x = items[takeIndex];
items[takeIndex] = null;
takeIndex = inc(takeIndex);
--count;
notFull.signal();
return x;
}
|
跟insert方法也很类似。 |
public class ConcurrentStack
AtomicReference
public void push(E item) {
Node
Node
do {
oldHead = head.get();
newHead.next = oldHead;
} while (! head.compareAndSet(oldHead, newHead));
}
public E pop() {
Node
Node
do {
oldHead = head.get();
if (oldHead == null)
return null;
newHead = oldHead.next;
}
while (! head.compareAndSet(oldHead
, newHead)); //核心代码
return oldHead.item;
}
static class Node
final E item;
Node
public Node(E item) { this.item = item; }
}
}
|
public class LinkedQueue
private AtomicReference
= new AtomicReference
private AtomicReference
public boolean put(E item) {
Node
while (true) {
Node
Node
if (curTail == tail.get()) {
if (residue == null) /* A */ {
if (
curTail.next.compareAndSet(null, newNode)) /* C */ {
tail.compareAndSet(curTail, newNode) /* D */ ;
return true;
}
} else {
tail.compareAndSet(curTail, residue) /* B,把尾指针向前移动 */;
}
}
}
}
private static class Node
final E item;
final AtomicReference
Node(E item, Node
this.item = item;
this.next = new AtomicReference
}
}
}
|
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return true (as specified by {@link Collection#add})
*/
public boolean
add(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);
return true;
} finally {
lock.unlock();
}
}
|
向CopyOnWriteArrayList中add方法的实现(向CopyOnWriteArrayList里添加元素),可以发现在添加的时候是需要加锁的,否则多线程写的时候会Copy出N个副本出来。 |
public E get(int index) {
return
get(getArray(), index);
}
|
读的时候不需要加锁,如果读的时候有多个线程正在向CopyOnWriteArrayList添加数据,读还是会读到旧的数据,因为写的时候不会锁住旧的CopyOnWriteArrayList |
public class ConcurrentHashMap
implements ConcurrentMap
final int segmentMask;
final int segmentShift;
final Segment
}
|
static final class Segment
private static final long serialVersionUID = 2249069246763182397L;
transient volatile int count; // * The number of elements in this segment's region.
transient int modCount;
transient int threshold; // * The table is rehashed when its size exceeds this threshold.
transient volatile HashEntry
final float loadFactor;
}
|