CurrentHashMap: 线程安全的HashMap
另一种线程安全的HashMap
public static Map m = Collections.synchronizedMap(new HashMap());
public V get(Object key) {
synchronized (mutex) {return m.get(key);}
}
CopyOnWriteArrayList: 适用于读多写少的场合,性能好于Vector
只有写写之间是会阻塞的。在写入的时候会进行一次自我复制,将修改的内容写入副本中,写完之后,再将修改完的副本替换原来的数据。
private volatile transient Object[] array;
public E get(int index){
return get(getArray(), index);
}
final Object[] getArray(){
return array;
}
private E get(Object[] a, int index){
return (E) a[index]
}
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();
}
}
ConcurrentLinkedQueue: 线程安全的链表队列
这是在高并发环境下性能最好的队列了,前提是高并发(至少1000个线程)
(据测试,性能和Vector差不了多少)
private static class Node<E>{
volatile E item;
volatile Node<E> next;
}
public boolean offer(E e) {
checkNotNull(e);
final Node<E> newNode = new Node<E>(e);
for (Node<E> t = tail, p = t;;) {
Node<E> q = p.next;
if (q == null) {
if (p.casNext(null, newNode)) {
if (p != t)
casTail(t, newNode);
return true;
}
}
else if (p == q)
p = (t != (t = tail)) ? t : head;
else
p = (p != t && t != (t = tail)) ? t : q;
}
}
public E poll() {
restartFromHead:
for (;;) {
for (Node<E> h = head, p = h, q;;) {
E item = p.item;
if (item != null && p.casItem(item, null)) {
if (p != h)
updateHead(h, ((q = p.next) != null) ? q : p);
return item;
}
else if ((q = p.next) == null) {
updateHead(h, p);
return null;
}
else if (p == q)
continue restartFromHead;
else
p = q;
}
}
}
boolean casItem(E cmp,E val){
return UNSAFE.compareAndSwapObject(this,itemOffset,cmp,val);
}
void lazySetNext(Node<E> val){
UNSAFE.putOrderedObject(this, nextOffset,val);
}
boolean casNext(Node<E> cmp, Node<E> val){
return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}
final void updateHead(Node<E> h,Node<E> p){
if(h != p && casHead(h,p)
h.lazySetNext(h);w
}
BlockingQueue: 一个接口,堵塞队列,作为数据共享的通道。就想物业的人设立一个邮箱,业主可以往这个邮箱里面投递投诉意见。业主会变,物业的工作人员也会变,但是信箱的作用不变。
实现接口的类有ArrayBlockingQueue和LinkedBlockingQueue。ArrayBlockingQueue适合实现有界队列,而LinkedBlockingQueue适合实现无界队列。
offer():将元素放入队列尾,满了会返回false || poll(): 头部取出一个元素,队列空返回null
put():将元素放入队列尾,满了会一直等待,直到有空闲 || take(): 头部取出,队列空则堵塞等待
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
public boolean offer(E e) {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count == items.length)
return false;
else {
enqueue(e);
return true;
}
} finally {
lock.unlock();
}
}
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return (count == 0) ? null : dequeue();
} finally {
lock.unlock();
}
}
ConcurrentSkipListMap: 跳表的实现
最低层的链表维护了跳表的所有元素,上一层链表为下一层链表的子集。跳表的元素都是有序的,查找时从顶层链表开始查找,发现被查找的元素大于当前链表的中的取值,则会进入下一层链表进行查找。
跳表是一种空间换时间的实现,但比HashMap好的是,跳表是有序的。