Java集合ConcurrentHashMap详解
什么是ConcurrentHashMap?
ConcurrentHashMap是一个线程安全、高效的哈希表实现。它和HashMap一样,也是基于哈希表实现的。与HashMap不同的是,ConcurrentHashMap提供了非常好的并发性能,允许多个线程同时读取和修改表中的元素。
在高并发的情况下,使用ConcurrentHashMap可以有效地解决线程安全问题,提供更好的性能。
ConcurrentHashMap的基本用法
1.创建ConcurrentHashMap
我们可以通过下面的语句来创建一个ConcurrentHashMap对象:
Map<String, String> map = new ConcurrentHashMap<>();
这里,我们创建了一个类型为Map
2.向ConcurrentHashMap中添加元素
向ConcurrentHashMap中添加元素可以使用put方法:
map.put("key1", "value1");
map.put("key2", "value2");
3.从ConcurrentHashMap中获取元素
从ConcurrentHashMap中获取元素可以使用get方法:
String value1 = map.get("key1");
String value2 = map.get("key2");
4.从ConcurrentHashMap中移除元素
从ConcurrentHashMap中移除元素可以使用remove方法:
map.remove("key1");
5.判断ConcurrentHashMap是否包含指定的键或值
判断ConcurrentHashMap是否包含指定的键可以使用containsKey方法,判断是否包含指定的值可以使用containsValue方法:
boolean containsKey = map.containsKey("key1");
boolean containsValue = map.containsValue("value1");
ConcurrentHashMap的高级用法
1.使用锁分离技术提高并发性能
ConcurrentHashMap采用了锁分离技术来提高并发性能。它将整个哈希表分为若干个锁单元,每个锁单元都可以独立地加锁和解锁。这样,当多个线程同时访问不同的锁单元时,它们之间就不会发生互斥,能够有效地提高并发性能。
2.ConcurrentHashMap的迭代器
ConcurrentHashMap的迭代器是弱一致的(weakly consistent),它提供了对元素的快速、无锁的遍历。虽然它不能保证在遍历过程中看到的所有修改都是最新的,但是它能够保证不会抛出ConcurrentModificationException异常。
虽然迭代器是弱一致的,但是对于插入新元素的线程来说,插入的新元素能够马上被迭代器看到。这是因为ConcurrentHashMap会将新元素放到下一个提交任务中。因此,插入新元素在迭代器中的顺序是有保证的。
3.ConcurrentHashMap的比较和排序
ConcurrentHashMap是无序的,它不保证元素的插入顺序。如果需要对ConcurrentHashMap中的元素进行排序或比较,我们可以使用Collections.sort方法。下面是一个例子:
List<Map.Entry<String, String>> list = new ArrayList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, String>>() {
@Override
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
return o1.getKey().compareTo(o2.getKey());
}
});
这里,我们首先将ConcurrentHashMap转换为一个包含Map.Entry元素的ArrayList,然后通过Collections.sort方法对ArrayList中的元素进行排序。排序方法使用key的比较值进行比较。
示例1:读写锁技术
下面是一个使用读写锁技术实现ConcurrentHashMap并发访问的例子:
public class ConcurrentMapExample {
private Map<Integer, Integer> map = new ConcurrentHashMap<>();
private ReadWriteLock lock = new ReentrantReadWriteLock();
public void write(Integer key, Integer value) {
lock.writeLock().lock();
try {
map.put(key, value);
} finally {
lock.writeLock().unlock();
}
}
public Integer read(Integer key) {
lock.readLock().lock();
try {
return map.get(key);
} finally {
lock.readLock().unlock();
}
}
}
该示例创建了一个ConcurrentMapExample类,提供了两个方法:write和read。在写操作时,使用写锁进行加锁;在读操作时,使用读锁进行加锁。这种方式能够有效地提高并发性能。
示例2:使用ConcurrentHashMap实现多线程统计字符出现次数
下面是一个使用ConcurrentHashMap实现多线程统计字符出现次数的例子:
public class CharacterCounter {
private ConcurrentHashMap<Character, Integer> characterCount = new ConcurrentHashMap<>();
public void count(Character c) {
characterCount.putIfAbsent(c, 0);
characterCount.compute(c, (key, val) -> val + 1);
}
public Integer getCount(Character c) {
return characterCount.get(c);
}
public Map<Character, Integer> getCharacterCount() {
return characterCount;
}
}
该示例创建了一个CharacterCounter类,提供了三个方法:count、getCount和getCharacterCount。在count方法中,使用putIfAbsent方法将字符c的计数器初始化为0;然后使用compute方法对计数器进行加1操作。在getCount方法中,使用get方法获取指定字符的计数器值。在getCharacterCount方法中,返回整个ConcurrentHashMap对象。
下面是一个使用该类的示例:
public class CharacterCounterTest {
public static void main(String[] args) throws InterruptedException {
final CharacterCounter cc = new CharacterCounter();
ExecutorService es = Executors.newFixedThreadPool(10);
String s = "hello world";
for (int i = 0; i < s.length(); i++) {
final char c = s.charAt(i);
es.execute(() -> {
cc.count(c);
});
}
es.shutdown();
es.awaitTermination(1, TimeUnit.MINUTES);
Map<Character, Integer> counts = cc.getCharacterCount();
for (Map.Entry<Character, Integer> entry : counts.entrySet()) {
System.out.println(entry.getKey() + " : " + entry.getValue());
}
}
}
该示例中,我们使用一个10个线程的线程池来并发地读取字符串中每个字符的计数器,最终将计数器结果输出。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java集合ConcurrentHashMap详解 - Python技术站