ConcrrentSkipListMap介绍和原理分析
一、前言:
JDK为我们提供了很多Map接口的实现,使得我们可以方便地处理Key-Value的数据结构。

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

通过上面的介绍我们可以对ConcurrentSkipListMap中基本操作的时间复杂度有个基本的了解:
| Operation | Time Complexity |
| Insertion | O(log N) |
| Removal | O(log N) |
| Check if contains | O(log N) |
| Enumerate in order | O(N) |
二、ConcurrentSkipListMap实例:
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap; public class ConcurrentSkipListMapExample {
public static void main(String[] args) {
ConcurrentNavigableMap<String, String> concurrentSkipListMap = new ConcurrentSkipListMap<String, String>();
concurrentSkipListMap.put("3", "Wednesday");
concurrentSkipListMap.put("2", "Tuesday");
concurrentSkipListMap.put("1", "Monday");
concurrentSkipListMap.put("5", "Friday");
concurrentSkipListMap.put("4", "Thursday"); NavigableSet<String> navigableSet = concurrentSkipListMap.descendingKeySet();
System.out.println("descendingKeySet: ");
Iterator<String> itr = navigableSet.iterator();
while (itr.hasNext()) {
String s = itr.next();
System.out.println(s);
}
System.out.println("ceilingEntry-2: " + concurrentSkipListMap.ceilingEntry("2"));
System.out.println("firstEntry: " + concurrentSkipListMap.firstEntry());
System.out.println("lastEntry: " + concurrentSkipListMap.lastEntry());
System.out.println("pollFirstEntry: " + concurrentSkipListMap.pollFirstEntry());
System.out.println("now firstEntry: " + concurrentSkipListMap.firstEntry());
System.out.println("pollLastEntry: " + concurrentSkipListMap.pollLastEntry());
System.out.println("now lastEntry: " + concurrentSkipListMap.lastEntry());
System.out.println("Entry-2: " + concurrentSkipListMap.get("2"));
} }
三、ConcurrentSkipListMap性能测试:
下面,我们来比较一下ConcurrentSkipListMap与TreeMap在并发情况下查询的性能状况。
我们会启动n个线程随机读取Map中的记录,每个线程会读取106次。

从测试结果,我们可以看出随着并发度的不断提高,ConcurrentSkipListMap相对于TreeMap的优势也越来越明显。
四、ConcurrentSkipListMap实现原理
skiplist数据结构介绍:
http://kenby.iteye.com/blog/1187303
concurrentskiplistmap实现并发的原理:
concurrentskiplistmap并没有使用lock来保证线程的并发访问和修改,而是使用了非阻塞算法来保证并发访问(Michael-Scott 算法)
也可以参考下面的博客(http://blog.csdn.net/jy3161286/article/details/22809913)
ConcrrentSkipListMap介绍和原理分析的更多相关文章
- 转载:AbstractQueuedSynchronizer的介绍和原理分析
简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础.使用的方法是继承,子类通过 ...
- AbstractQueuedSynchronizer的介绍和原理分析(转)
简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础.使用的方法是继承,子类通过 ...
- Servlet过滤器介绍之原理分析
zhangjunhd 的BLOG 写留言去学院学习发消息 加友情链接进家园 加好友 博客统计信息 51CTO博客之星 用户名:zhangjunhd 文章数:110 评论数:858 访问量:19 ...
- Hadoop数据管理介绍及原理分析
Hadoop数据管理介绍及原理分析 最近2014大数据会议正如火如荼的进行着,Hadoop之父Doug Cutting也被邀参加,我有幸听了他的演讲并获得亲笔签名书一本,发现他竟然是左手写字,当然这个 ...
- AbstractQueuedSynchronizer的介绍和原理分析
简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础.使用的方法是继承,子类通过 ...
- 转:AbstractQueuedSynchronizer的介绍和原理分析
引自:http://ifeve.com/introduce-abstractqueuedsynchronizer/ 简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同 ...
- TKmybatis的框架介绍和原理分析及Mybatis新特性
tkmybatis是在mybatis框架的基础上提供了很多工具,让开发更加高效,下面来看看这个框架的基本使用,后面会对相关源码进行分析,感兴趣的同学可以看一下,挺不错的一个工具 实现对员工表的增删改查 ...
- TKmybatis的框架介绍和原理分析及Mybatis新特性演示
tkmybatis是在mybatis框架的基础上提供了很多工具,让开发更加高效,下面来看看这个框架的基本使用,后面会对相关源码进行分析,感兴趣的同学可以看一下,挺不错的一个工具 实现对员工表的增删改查 ...
- logistic回归介绍以及原理分析
1.什么是logistic回归? logistic回归虽然说是回归,但确是为了解决分类问题,是二分类任务的首选方法,简单来说,输出结果不是0就是1 举个简单的例子: 癌症检测:这种算法输入病理图片并且 ...
随机推荐
- cxDBTreelist一些使用方法
一.导出EXCEL TXT HTML: uses cxTLExportLink; cxExportTLToEXCEL(dm.SaveDialog.FileName,cxDBTreeList1, ...
- Hadoop初探
本文转自:https://blog.csdn.net/column/details/14334.html 前言 Hadoop是什么? 用百科上的话说:“Hadoop是一个由Apache基金会所开发的分 ...
- gitlab账号注册及分组
.开启注册邮箱验证 admin area -->setting-->Sign-up restrictions-->勾选Send confirmation email on sign- ...
- mac下面安装redis
本文只记录了在homebrew下面安装redis的过程,过程比较简单,作为自己以后翻阅用吧, 首先安装homebrew,打开终端,在终端下面允许下面的命令(不要用root用户): /usr/bin/r ...
- scrapy学习笔记(三):使用item与pipeline保存数据
scrapy下使用item才是正经方法.在item中定义需要保存的内容,然后在pipeline处理item,爬虫流程就成了这样: 抓取 --> 按item规则收集需要数据 -->使用pip ...
- Linux内核0.11 bootsect文件说明
一.总体功能介绍 这是关于Linux-kernel-0.11中boot文件夹下bootsect.s源文件的说明,其中涉及到了一些基础知识可以参考这两篇文章. 操作系统启动过程 软盘相关知识和通过BIO ...
- MSTSC 修改端口的简单方法 3389
1. 3389端口太过危险 最简单的办法是 修改默认端口方法非常简单. 2. win+r 打开运行, 输入 regedit 打开 注册表 3. 在地址栏输入 远程的服务的路径 输入的内容为: 计算机 ...
- Linux下更改正确国内时间
Linux使用小Tips 整理些Linux些常遇到的问题. Linux下设置时间 提供两种最根本有效的方式,就是更改时区.这里以更改为国内上海时间例子,其他地方时区同理. 方法一 备份文件 mv /e ...
- HDU3046_Pleasant sheep and big big wolf
给一个n*m的数字阵,1表示羊的位置,2表示狼的位置,0表示没有东西,可以通过.在每个格子的4边都可以建立围栏,有围栏的话狼是不能通过的. 现在求最少建立多少围栏能够保证狼无法接触到羊. 题目的模型很 ...
- 纯css实现长宽等比例的div
现代网站页面基本都需要响应式,一个div的长宽往往我们都设置为百分之多少,这个百分之是相对于父容器动态计算的 这样在浏览器宽度变化之后,我们的元素也能自动更新长宽.例如:我们在页面上摆了一个div,这 ...