ConcurrentHashMap使用示例
2015-11-14 10:01
197 查看
ConcurrentHashMap是并发效率更高的Map,用来替换其他线程安全的Map容器,比如Hashtable和Collections.synchronizedMap。实际上,并发执行时,线程安全的容器只能保证自身的数据不被破坏,但无法保证业务的行为是否正确。错误的理解这里的线程安全,不恰当的使用ConcurrentHashMap,往往会导致出现问题。
举个例子:
当然可以用锁解决这个问题,但是也可以使用ConcurrentMap定义的方法:
public static void demo1() {
final Map<String, Integer> count = new ConcurrentHashMap<>();
final CountDownLatch endLatch = new CountDownLatch(2);
Runnable task = new Runnable() {
@Override
public void run() {
Integer oldValue, newValue;
for (int i = 0; i < 5; i++) {
while (true) {
oldValue = count.get("a");
if (null == oldValue) {
newValue = 1;
if (count.putIfAbsent("a", newValue) == null) {
break;
}
} else {
newValue = oldValue + 1;
if (count.replace("a", oldValue, newValue)) {
break;
}
}
}
}
endLatch.countDown();
}
};
new Thread(task).start();
new Thread(task).start();
try {
endLatch.await();
System.out.println(count);
} catch (Exception e) {
e.printStackTrace();
}
}
由于ConcurrentMap中不能保存value为null的值,所以需要处理不存在和已存在两种情况,不过可以使用AtomicInteger来替代。
举个例子:
public static void demo1() { final Map<String, Integer> count = new ConcurrentHashMap<>(); final CountDownLatch endLatch = new CountDownLatch(2); Runnable task = new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { Integer value = count.get("a"); if (null == value) { count.put("a", 1); } else { count.put("a", value + 1); } } endLatch.countDown(); } }; new Thread(task).start(); new Thread(task).start(); try { endLatch.await(); System.out.println(count); } catch (Exception e) { e.printStackTrace(); } }demo1是两个线程操作ConcurrentHashMap,意图将value变为10。但是,因为多个线程用相同的key调用时,很可能会覆盖相互的结果,造成记录的次数比实际出现的次数少。
当然可以用锁解决这个问题,但是也可以使用ConcurrentMap定义的方法:
V putIfAbsent(K key, V value) 如果key对应的value不存在,则put进去,返回null。否则不put,返回已存在的value。 boolean remove(Object key, Object value) 如果key对应的值是value,则移除K-V,返回true。否则不移除,返回false。 boolean replace(K key, V oldValue, V newValue) 如果key对应的当前值是oldValue,则替换为newValue,返回true。否则不替换,返回false。于是对demo1进行改进:
public static void demo1() {
final Map<String, Integer> count = new ConcurrentHashMap<>();
final CountDownLatch endLatch = new CountDownLatch(2);
Runnable task = new Runnable() {
@Override
public void run() {
Integer oldValue, newValue;
for (int i = 0; i < 5; i++) {
while (true) {
oldValue = count.get("a");
if (null == oldValue) {
newValue = 1;
if (count.putIfAbsent("a", newValue) == null) {
break;
}
} else {
newValue = oldValue + 1;
if (count.replace("a", oldValue, newValue)) {
break;
}
}
}
}
endLatch.countDown();
}
};
new Thread(task).start();
new Thread(task).start();
try {
endLatch.await();
System.out.println(count);
} catch (Exception e) {
e.printStackTrace();
}
}
由于ConcurrentMap中不能保存value为null的值,所以需要处理不存在和已存在两种情况,不过可以使用AtomicInteger来替代。
public static void demo1() { final Map<String, AtomicInteger> count = new ConcurrentHashMap<>(); final CountDownLatch endLatch = new CountDownLatch(2); Runnable task = new Runnable() { @Override public void run() { AtomicInteger oldValue; for (int i = 0; i < 5; i++) { oldValue = count.get("a"); if (null == oldValue) { AtomicInteger zeroValue = new AtomicInteger(0); oldValue = count.putIfAbsent("a", zeroValue); if (null == oldValue) { oldValue = zeroValue; } } oldValue.incrementAndGet(); } endLatch.countDown(); } }; new Thread(task).start(); new Thread(task).start(); try { endLatch.await(); System.out.println(count); } catch (Exception e) { e.printStackTrace(); } }
相关文章推荐
- CRC校验
- android studio + opencv开发,objectMatch摄像头实时处理
- iOS开发规范
- 通过静态内部类进行单例
- 使用<link> 标签定义浏览器标题栏小图标
- CentOS6.4编译安装Gcc5.2.0
- Hexo中使用多说评论系统
- mysql 5.6 版本,对在使用的表进行分区
- 加速计_陀螺仪_磁力计
- iOS9.2 PCH文件的创建和使用
- DropDownList的用法
- 9.php 数组知识,date,文件upload
- 使用jsp:include控制动态内容的方法
- Android——布局layout中的一些属性
- Leetcode Unique Binary Search Trees
- HDU 5483 Nux Walpurgis
- 友盟用户反馈(官方文档学习而来)
- google-play-services_lib 添加,google-play-services_lib 这个文件夹在哪里,admob
- 1.UIView知识总结
- Computer Vision && Deep learning 岗位公司实习的要求