Java并发容器——ConcurrentSkipListMap

时间:2022-03-20 20:49:09
当我们希望快速存取<Key, Value>键值对时我们可以使用HashMap。
当我们希望在多线程并发存取<Key, Value>键值对时,我们会选择ConcurrentHashMap。
TreeMap则会帮助我们保证数据是按照Key的自然顺序或者compareTo方法指定的排序规则进行排序。
OK,那么当我们需要多线程并发存取<Key, Value>数据并且希望保证数据有序时,我们需要怎么做呢?
。。。。。。
也许,我们可以选择ConcurrentTreeMap。不好意思,JDK没有提供这么好的数据结构给我们。
当然,我们可以自己添加lock来实现ConcurrentTreeMap,但是随着并发量的提升,lock带来的性能开销也随之增大。
Don't cry......,JDK6里面引入的ConcurrentSkipListMap也许可以满足我们的需求。

构造方法

public ConcurrentSkipListMap() {
this.comparator = null;
initialize();
}

/**
* Constructs a new, empty map, sorted according to the specified
* comparator.
*
* @param comparator the comparator that will be used to order this map.
* If {@code null}, the {@linkplain Comparable natural
* ordering} of the keys will be used.
*/

public ConcurrentSkipListMap(Comparator<? super K> comparator) {
this.comparator = comparator;
initialize();
}

从构造方法可以看出,需传入一个Comparator接口,实现添加数据时,对key自定义排序。
若没有传入Comparator,则要求key实现了comparable接口。

注意size()方法

在ConcurrentSkipListMap中尽量避免使用size方法:

public int size() {
long count = 0;
for (Node<K,V> n = findFirst(); n != null; n = n.next) {
if (n.getValidValue() != null)
++count;
}
return (count >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) count;
}

从源码可以看出size()方法就是遍历一遍,这是很消耗性能的。
那如何判断ConcurrentSkipListMap是否为空呢,当然使用isEmpty

public boolean isEmpty() {
return findFirst() == null;
}

实现原理

底层使用了跳表(SkipList)数据结构,具体可百度。
具体实现参考:http://blog.csdn.net/coslay/article/details/44819823