treemap

深入一致性哈希(Consistent Hashing)算法原理

霸气de小男生 提交于 2020-03-02 02:13:11
本文为实现分布式任务调度系统中用到的一些关键技术点分享——Consistent Hashing算法原理和Java实现,以及效果测试。(代码实现见: https://github.com/yaohonv/pingpong/tree/master/consistenthashing ) 背景介绍 一致性Hashing在分布式系统中经常会被用到, 用于尽可能地降低节点变动带来的数据迁移开销。Consistent Hashing算法在1997年就在论文 Consistenthashing and random trees 中被提出。 先来简单理解下Hash是解决什么问题。假设一个分布式任务调度系统,执行任务的节点有n台机器,现有m个job在这n台机器上运行,这m个Job需要逐一映射到n个节点中一个,这时候可以选择一种简单的Hash算法来让m个Job可以均匀分布到n个节点中,比如 hash(Job)%n ,看上去很完美,但考虑如下两种情形: n个节点中有一个宕掉了,这时候节点数量变更为n-1,此时的映射公式变成 hash(Job)%(n-1) 由于Job数量增加,需要新增机器,此时的映射公式变成 hash(Job)%(n+1) 1、2两种情形可以看到,基本上所有的Job会被重新分配到跟节点变动前不同的节点上,意味着需要迁移几乎所有正在运行的Job,想想这样会给系统带来多大的复杂性和性能损耗。

Java中散列表、树所对应的容器类。HashMap如何解决hash冲突的

你。 提交于 2020-03-02 00:11:18
散列表(哈希表)对应的容器 HashMap、hashset、HashTable、concurrentHashMap 树对应的容器 treemap、treeset 什么是Hash冲突 两个不同的 key 计算出来的 hashcode 值相同。 解决方法 开放定址法 key=(f(key)+di) mod m 链地址法 再哈希 来源: oschina 链接: https://my.oschina.net/u/4141148/blog/3071076

Java中常见数据结构:List与Map

試著忘記壹切 提交于 2020-03-01 09:52:09
1:集合 Collection(单列集合) List(有序,可重复) ArrayList 底层数据结构是数组,查询快,增删慢 线程不安全,效率高 Vector 底层数据结构是数组,查询快,增删慢 线程安全,效率低 LinkedList 底层数据结构是链表,查询慢,增删快 线程不安全,效率高 Set(无序,唯一) HashSet 底层数据结构是哈希表(实际上是一个HashMap实例)。 哈希表依赖两个方法:hashCode()和equals() 执行顺序: 首先判断hashCode()值是否相同 是:继续执行equals(),看其返回值 是true:说明元素重复,不添加 是false:就直接添加到集合 否:就直接添加到集合 最终: 自动生成hashCode()和equals()即可 LinkedHashSet 底层数据结构由链表和哈希表组成。 由链表保证元素有序。 由哈希表保证元素唯一。 TreeSet 底层数据结构是红黑树。(是一种自平衡的二叉树) 如何保证元素唯一性呢? 根据比较的返回值是否是0来决定 如何保证元素的排序呢? 两种方式 自然排序(元素具备比较性) 让元素所属的类实现Comparable接口 比较器排序(集合具备比较性) 让集合接收一个Comparator的实现类对象 Map(双列集合) A:Map集合的数据结构仅仅针对键有效,与值无关。 B

Java HashMap的工作原理 及各种Map区别

被刻印的时光 ゝ 提交于 2020-02-29 06:59:32
一、Java HashMap的工作原理 jdk1.7下HashMap数据结构:数组加链表,链表长度没有8的限制; jdk1.8 HashMap数据结构:数组+链表+红黑树;链表超过8会转存为红黑树; 1.jdk1.8 中HashMap的put工作原理: 1)、对key做null检查。如果key是null,会被存储到table[0],因为null的hash值总是0。 2)、判断当前桶是否为空,空的就需要初始化(resize 中会判断是否进行初始化) 给定的默认容量为 16,负载因子为 0.75。Map 在使用过程中不断的往里面存放数据,当数量达到了 16 * 0.75 = 12 就需要将当前 16 的容量进行扩容,而扩容这个过程涉及到 rehash、复制数据等操作,所以非常消耗性能。 3)、获取key的hashCode值(可以理解为内存地址位置,如:3254239),并对该32位hashCode值进行高低16位的异或运算;得到hash值(如:3812);(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 4)、将获取到的hash值进行一个求模运算(相当于3812%16),得到该key对应的索引位置;if ((p = tab[i = (n - 1) & hash]) == null);该位置肯定不会超过16位; 5)、根据当前

为什么Map桶中个数超过8才转为红黑树

爱⌒轻易说出口 提交于 2020-02-28 17:50:31
要弄明白这个问题,我们首先要明白为什么要转换,这个问题比较简单,因为Map中桶的元素初始化是链表保存的,其查找性能是O(n),而树结构能将查找性能提升到O(log(n))。当链表长度很小的时候,即使遍历,速度也非常快,但是当链表长度不断变长,肯定会对查询性能有一定的影响,所以才需要转成树。至于为什么阈值是8,我想,去源码中找寻答案应该是最可靠的途径。 8这个阈值定义在HashMap中,如下所示,这段注释只说明了8是bin(bin就是bucket,即HashMap中hashCode值一样的元素保存的地方)从链表转成树的阈值,但是并没有说明为什么是8: /** * The bin count threshold for using a tree rather than list for a * bin. Bins are converted to trees when adding an element to a * bin with at least this many nodes. The value must be greater * than 2 and should be at least 8 to mesh with assumptions in * tree removal about conversion back to plain bins upon

java中散列表、树所对应的的容器类。HashMap如何解决冲突

六眼飞鱼酱① 提交于 2020-02-28 15:58:25
java中散列表、树所对应的的容器类 散列表:hashmap,hashtable,concurrentHashmap 树:hashset,treemap,treeset jdk7与jdk8中HashMap的区别 jdk7中hashMap采用数组+链表,如果过多的节点在hash时发生碰撞,如果要查找其中一个节点,需要O(n)的查找时间。 jdk7中hashMap采用数组+链表/红黑树,当某个桶位达到某个阈值时,链表将转化为红黑树,红黑树时间复杂度O(nlogn) HashMap如何解决冲突 1.开放定址法: 通过探测算法,当一个槽位已经被占用情况下继续查找下一个 2.链地址法(数组+链表) 3.再哈希 准备多个散列函数,当发生冲突时,再选择一个散列函数进行散列。 HashMap的工作原理 HashMap 底层是 数组 和 单向链表 实现,数组中的每个元素都是 链表 ,由 Node 内部类(实现 Map.Entry<K,V>接口) 实现,HashMap 通过 put & get 方法存储和获取。 HashCode是定位(存储位置),equals是定性(两者是否相等) 存储对象时,将K/V传给put()方法: ①hash(K)计算K的hash,结合数组长度,计算数组下标 ②调整数据大小(当容器中的元素个数大于 capacity * loadfactor 时,容器会进行扩容resize 为

Java基础知识的27个点

被刻印的时光 ゝ 提交于 2020-02-28 03:22:26
1、JAVA中的几种基本数据类型是什么,各自占用多少字节。 2、String类能被继承吗,为什么 不能。在Java中,只要是被定义为final的类,也可以说是被final修饰的类,就是不能被继承的。 3、String,Stringbuffer,StringBuilder的区别。 4、ArrayList和LinkedList有什么区别。 简单的区别: 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 (LinkedList是双向链表,有next也有previous) 2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 深度的区别: 1.对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。对ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象。 2.在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。 3

使用HashMap的时候小心点

点点圈 提交于 2020-02-27 15:56:39
Map家族介绍 我们都知道 HashMap 是线程不安全的,但是 HashMap 的使用频率在所有 Map 中确实属于比较高的。因为它可以满足我们大多数的场景了。 看一眼Map家族的关系图: Map 是一个接口,我们常用的实现类有 HashMap 、 LinkedHashMap 、 TreeMap , HashTable 。 HashMap HashMap 根据 key 的·值来保存value,需要注意的是, HashMap 不保证遍历的顺序和插入的顺序是一致的。 HashMap 允许有一条记录的 key 为 null ,但是对值是否为 null 不做要求。 HashTable HashTable 类是线程安全的,它使用 synchronize 来做线程安全,全局只有一把锁,在线程竞争比较激烈的情况下 hashtable 的效率是比较低下的。因为当一个线程访问 hashtable 的同步方法时,其他线程再次尝试访问的时候,会进入阻塞或者轮询状态,比如当线程1使用put进行元素添加的时候,线程2不但不能使用put来添加元素,而且不能使用get获取元素。所以,竞争会越来越激烈。相比之下, ConcurrentHashMap 使用了分段锁技术来提高了并发度,不在同一段的数据互相不影响,多个线程对多个不同的段的操作是不会相互影响的。每个段使用一把锁。所以在需要线程安全的业务场景下,推荐使用

总结:延时任务队列的原理与实现

不想你离开。 提交于 2020-02-27 11:42:45
延时任务有别于定式任务,定式任务往往是固定周期的,有明确的触发时间。而延时任务一般没有固定的开始时间,它常常是由一个事件触发的,而在这个事件触发之后的一段时间内触发另一个事件。也就是说,任务事件生成时并不想让消费者立即拿到,而是延迟一定时间后才接收到该事件进行消费。 延迟任务相关的业务场景如下: 场景一:在订单系统中,一个用户某个时刻下单之后通常有30分钟的时间进行支付,如果30分钟之内没有支付成功,那么这个订单将自动进行过期处理。 场景二:用户某个时刻通过手机远程遥控家里的智能设备在指定的时间进行工作。这时就可以将用户指令发送到延时队列,当指令设定的时间到了再将指令推送到只能设备。 下面我们来探讨一些方案,其实这些方案没有好坏之分,和系统架构一样,只有最适合。对于数据量较小的情况下,任意一种方案都可行,考虑的是简单明了和开发速度,尽量避免把系统搞复杂了。而对于数据量较大的情况下,就需要有一些选择,并不是所有的方案都适合了。 解决方式 定时器轮询遍历数据库记录 JDK的DelayQueue JDK ScheduledExecutorService 时间轮(netty) 利用quartz等定时任务 Redis的ZSet实现 rabbitMq实现延时队列 定时器轮询遍历数据库记录 这是比较常见的一种方式,所有的订单或者所有的命令一般都会存储在数据库中

集合的一些坑

只愿长相守 提交于 2020-02-27 05:40:29
1 集合的一些坑 当集合的元素是自定义类时,自定义类强制实现 equals 和 hashCode 方法,并且两个都要实现。 在集合中,除了 TreeMap 和 TreeSet 是通过比较器比较元素大小外,其余的集合类在判断索引位置和相等时,都会使用到 equals 和 hashCode 方法,这个在之前的源码解析中,我们有说到,所以当集合的元素是自定义类时,我们强烈建议覆写 equals 和 hashCode 方法,我们可以直接使用 IDEA 工具覆写这两个方法,非常方便; 所有集合类,在 for 循环进行删除时,如果直接使用集合类的 remove 方法进行删除,都会快速失败,报 ConcurrentModificationException 的错误,所以在任意循环删除的场景下,都建议使用迭代器进行删除; 我们把数组转化成集合时,常使用 Arrays.asList(array),这个方法有两个坑,代码演示坑为: public void testArrayToList ( ) { Integer [ ] array = new Integer [ ] { 1 , 2 , 3 , 4 , 5 , 6 } ; List < Integer > list = Arrays . asList ( array ) ; // 坑1:修改数组的值,会直接影响原 list log . info (