ConcurrentHashMap 1.7原理

HashTable与HashMap区别

1.HashTable  线程是安全的 (使用synchronized)
2.HashMap    线程是不安全 (没有使用锁)
3.HashMap    允许存放key值 null 存放在  index=0位置
4.HashTable  不允许存放key为null

1.HashMap实现不同步, 线程不安全  HashTable线程安全  HashMap中的key-value都是存储在Entry中的
2.继承不同
    Hashtable 继承 Dictionary 类,而 HashMap  继承 AbstractMap
    public class Hashtable extends Dictionary implements Map
    public class HashMap extends  AbstractMap implements Map
3.Hashtable中的方法是同步的, 而HashMap中的方法在缺省情况下是非同步的, 在多线程并发的环境下, 可以直接使用Hashtable, 但是要使用HashMap的话就要自己增加同步处理了。  
4.Hashtable中, key 和 value 都不允许出现 null 值, 在 HashMap 中, null 可以作为键,这样的键只有一个, 可以有一个或多个键所对应的值为 null, 当get() 方法返回 null 值时, 即可以表示 HashMap 中没有该键, 也可以表示该键所对应的值为 null, 因此, 在 HashMap 中不能由 get() 方法来判断 HashMap 中是否存在某个键, 而应该用 containsKey() 方法来判断  
5.哈希值的使用不同, HashTable直接使用对象的hashCode, 而HashMap重新计算hash值

为什么不使用HashTable

HashTable 底层 通过 synchronized 保证线程安全性问题
保证线程安全性问题---加上锁---发生锁的竞争

HashTable 当多个线程 在访问 get或者put操作的时候
会发生this锁的竞争,多个线程竞争锁 最终只会有一个
线程获取到this锁,获取不到的this锁 可能会阻塞等待
最终将我们的 HashTable 中 get 或者put方法改成
单线程执行 效率是非常的低
在多线程的情况下 不推荐使用 HashTable ConcurrentHashMap

jdk官方不推荐在多线程的情况下使用HashTable或者HashMap, 建议使用ConcurrentHashMap分段HashMap, 效率非常高
核心思想: 减少多个线程锁竞争   不会在访问同一个HashTable

ConcurrentHashMap 1.7底层实现原理

ConcurrentHashMap将一个大的HashTable集合拆分成n多个不同的小的HashTable(Segment), 默认的情况下是分成16个不同的Segment, 每个Segment中都有自己独立的HashEntry<K,V>[] table

ConcurrentHashMap 1.7 底层采用 分段锁设计
将一个大的HashTable线程安全的集合, 拆分成n多个小的 HashTable集合, 默认初始化16个小的HashTable集合
如果同时16个线程 最终计算index值 落地到不同的小的HashTable集合 不会发生锁的竞争, 同时可以支持16个线程 访问ConcurrentHashMap  写的操作, 效率非常高

如果多个线程写入的key 最终计算落地到同一个小的HashTable集合中, 就会发生锁的竞争


ConcurrentHashMap 1.8 取消了分段锁的设计

ConcurrentHashMap 1.7 计算两次index

ConcurrentHashMap  1.7版本需要计算出2次 index值。
第一次计算index=  计算key存放到具体小的HashTable
第二次计算index=  计算key存放到具体小的HashTable,对应具体 数组 index位置。
HashTable ---- 数组 + 链表实现

手写ConcurrentHashMap 1.7

import java.util.Hashtable;

public class MyConcurrentHashMap<K, V> {
    /**
     * 创建一个 存放 小的HashTable集合
     */
    private Hashtable<K, V>[] segments;

    public MyConcurrentHashMap() {
        //默认的情况下, 初始化16分小的HashTable
        segments = new Hashtable[16];
        for (int i = 0; i < segments.length; i++) {
            segments[i] = new Hashtable<>();
        }
    }

    public MyConcurrentHashMap(Integer length) {
        segments = new Hashtable[length];
        for (int i = 0; i < segments.length; i++) {
            segments[i] = new Hashtable<>();
        }
    }

    public void put(K k, V v) {
        //先计算key存放具体小的hashTable 集合中
        int segmentIndex = k.hashCode() % segments.length;
        //再将key存入具体的小的hashTable 集合中
        segments[segmentIndex].put(k, v);
    }

    public V get(K k) {
        int segmentIndex = k.hashCode() % segments.length;
        return segments[segmentIndex].get(k);
    }

    public static void main(String[] args) {
        MyConcurrentHashMap<String, String> map = new MyConcurrentHashMap<>();
        map.put("a", "a");
        map.put("b", "b");
        System.out.println(map.get("a"));
        System.out.println(map.get("b"));
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值