005-多线程-集合-Map-ConcurrentSkipListMap
一、概述
ConcurrentSkipListMap是线程安全的有序的哈希表,适用于高并发的场景。
ConcurrentSkipListMap和TreeMap,它们虽然都是有序的哈希表。但是,第一,它们的线程安全机制不同,TreeMap是非线程安全的,而ConcurrentSkipListMap是线程安全的。第二,ConcurrentSkipListMap是通过跳表实现的,而TreeMap是通过红黑树实现的。
关于跳表(Skip List),它是平衡树的一种替代的数据结构,但是和红黑树不相同的是,跳表对于树的平衡的实现是基于一种随机化的算法的,这样也就是说跳表的插入和删除的工作是比较简单的。
1.1、原理和数据结构

说明:
先以数据“7,14,21,32,37,71,85”序列为例,来对跳表进行简单说明。
跳表分为许多层(level),每一层都可以看作是数据的索引,这些索引的意义就是加快跳表查找数据速度。每一层的数据都是有序的,上一层数据是下一层数据的子集,并且第一层(level 1)包含了全部的数据;层次越高,跳跃性越大,包含的数据越少。
跳表包含一个表头,它查找数据时,是从上往下,从左往右进行查找。现在“需要找出值为32的节点”为例,来对比说明跳表和普遍的链表。
情况1:链表中查找“32”节点
路径如下图1-02所示:

需要4步(红色部分表示路径)。
情况2:跳表中查找“32”节点
路径如下图1-03所示:

忽略索引垂直线路上路径的情况下,只需要2步(红色部分表示路径)。
下面说说Java中ConcurrentSkipListMap的数据结构。
(01) ConcurrentSkipListMap继承于AbstractMap类,也就意味着它是一个哈希表。
(02) Index是ConcurrentSkipListMap的内部类,它与“跳表中的索引相对应”。HeadIndex继承于Index,ConcurrentSkipListMap中含有一个HeadIndex的对象head,head是“跳表的表头”。
(03) Index是跳表中的索引,它包含“右索引的指针(right)”,“下索引的指针(down)”和“哈希表节点node”。node是Node的对象,Node也是ConcurrentSkipListMap中的内部类。
1.2、示例
/*
* ConcurrentSkipListMap是“线程安全”的哈希表,而TreeMap是非线程安全的。
*
* 下面是“多个线程同时操作并且遍历map”的示例
* (01) 当map是ConcurrentSkipListMap对象时,程序能正常运行。
* (02) 当map是TreeMap对象时,程序会产生ConcurrentModificationException异常。
*/
public class ConcurrentSkipListMapDemo1 { // TODO: map是TreeMap对象时,程序会出错。
//private static Map<String, String> map = new TreeMap<String, String>();
private static Map<String, String> map = new ConcurrentSkipListMap<String, String>(); public static void main(String[] args) { // 同时启动两个线程对map进行操作!
new MyThread("a").start();
new MyThread("b").start();
} private static void printAll() {
String key, value;
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
key = (String) entry.getKey();
value = (String) entry.getValue();
System.out.print("(" + key + ", " + value + "), ");
}
System.out.println();
} private static class MyThread extends Thread {
MyThread(String name) {
super(name);
} @Override
public void run() {
int i = 0;
while (i++ < 6) {
// “线程名” + "序号"
String val = Thread.currentThread().getName() + i;
map.put(val, "0");
// 通过“Iterator”遍历map。
printAll();
}
}
}
}
1.3、使用场景
二、源码分析
005-多线程-集合-Map-ConcurrentSkipListMap的更多相关文章
- 【死磕 Java 集合】— ConcurrentSkipListMap源码分析
转自:http://cmsblogs.com/?p=4773 [隐藏目录] 前情提要 简介 存储结构 源码分析 主要内部类 构造方法 添加元素 添加元素举例 删除元素 删除元素举例 查找元素 查找元素 ...
- Java集合—Map
简介 Map用户保存具有映射关系的数据,因此Map集合里保存着两组数,一组值用户保存Map里的key,另一组值用户保存Map里的value,key和value都可以是任何引用类型的数据.Map的key ...
- 备战金三银四!一线互联网公司java岗面试题整理:Java基础+多线程+集合+JVM合集!
前言 回首来看2020年,真的是印象中过的最快的一年了,真的是时间过的飞快,还没反应过来年就夸完了,相信大家也已经开始上班了!俗话说新年新气象,马上就要到了一年之中最重要的金三银四,之前一直有粉丝要求 ...
- Java集合Map接口与Map.Entry学习
Java集合Map接口与Map.Entry学习 Map接口不是Collection接口的继承.Map接口用于维护键/值对(key/value pairs).该接口描述了从不重复的键到值的映射. (1) ...
- (10)集合之双列集合Map,HashMap,TreeMap
Map中的元素是两个对象,一个对象作为键,一个对象作为值.键不可以重复,但是值可以重复. 看顶层共性方法找子类特有对象. Map与Collection在集合框架中属并列存在 Map存储的是键值对 Ma ...
- 【由浅入深理解java集合】(五)——集合 Map
前面已经介绍完了Collection接口下的集合实现类,今天我们来介绍Map接口下的两个重要的集合实现类HashMap,TreeMap.关于Map的一些通用介绍,可以参考第一篇文章.由于Map与Lis ...
- (7)Java数据结构--集合map,set,list详解
MAP,SET,LIST,等JAVA中集合解析(了解) - clam_clam的专栏 - CSDN博---有颜色, http://blog.csdn.net/clam_clam/article/det ...
- 双列集合Map
1.双列集合Map,就是存储key-value的键值对. 2.hashMap中键必须唯一,值可以不唯一. 3.主要方法:put添加数据 getKey---通过key获取数据 keySet- ...
- 12:集合map、工具类
一.map集合 Map:一次添加一对元素.Collection 一次添加一个元素. Map也称为双列集合,Collection集合称为单列集合. 其实map集合中存储的就是键值对(结婚证书), map ...
- 20_java之集合Map
01Map集合概述 A:Map集合概述: 我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同 a:Collection中的集合,元素是孤立 ...
随机推荐
- charles 手机证书下载安装
本文参考:charles 手机证书下载安装 本文的Charles,适应windows/MAC/IOS/Android,避免抓包HTTPS失败和乱码: 用的版本是V4.1.2,其它版本原理类似: cha ...
- shell 文本替换 ---出现--- sed:-e 表达式 #1,字符 8:“s”的未知选项
需要替换的行为: monitor.url=http://192.168.25.100:8443/rest 查询资料得知,报错是因为替换的字符串包含有分隔符/ 所以这行改一下分隔符就可以解决问题了 ( ...
- 华为OJ:字符串处理
#include <iostream> #include <stdlib.h> #include <string> #include <sstream> ...
- JavaScript常用类库推荐
Axios Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中 [中文说明], [Github], [教程] Lodash 一致性.模块化.高性能的 Jav ...
- Java位运算总结:位运算用途广泛
前天几天研究了下JDK的Collection接口,本来准备接着研究Map接口,可是一查看HashMap类源码傻眼咯,到处是位运算实现,所以我觉得还是有必要先补补位运算知识,不然代码看起来有点费力.今天 ...
- 使用Costura.Fody插件将自己写的程序打包成一个可以独立运行的EXE文件
我们在开发程序的时候会引用很多DLL文件,在程序完成编写后,如果不把这些引用的DLL打包,不能在其他电脑运行,那么很多同学可能在想了,能不能把我们编写好的程序打包成一个EXE文件,最好双击就能运行,当 ...
- 学到了林海峰,武沛齐讲的Day18-4 文件操作
print(data.decode('utf-8')) 转换utf-8格式f.write('杨件'.encode('utf-8')) 转换为bytes# f.write(bytes('1111\n', ...
- 066_调整虚拟机内存参数的 shell 脚本
#!/bin/bash#脚本通过调用 virsh 命令实现对虚拟机的管理,如果没有该命令,需要安装 libvirt-client 软件包 cat << EOF1.调整虚拟机最大内存数值2. ...
- P3939 数颜色 线段树动态开点
P3939 数颜色 线段树动态开点 luogu P3939 水.直接对每种颜色开个权值线段树即可,注意动态开点. #include <cstdio> #include <algori ...
- (1)打鸡儿教你Vue.js
当今世界不会Vue.js,前端必定路难走 一个JavaScript MVVM库 以数据驱动和组件化的思想构建的 Vue.js是数据驱动 HTML/CSS/JavaScript/ES6/HTTP协议/V ...