heima并发---ConcurrentHashMap系列后续-p1-p2-281和以后

地址:https://www.bilibili.com/video/bv1x741117jq/?spm_id_from=333.788.b_636f6d6d656e74.7

JDK7的HashMap。

---

链表:JDk7是插入到链表的头部是比较快的,插到尾部是比较慢的因为需要遍历的。

--

get的方法是如何实现的?首先获得key的hashCode重写的话就用重写的,否则用系统的,这个hash是比较麻烦的,之后取余(&(n-1)),然后找到在数组的下标。

--

头插法,先插入到头节点,然后向后移动一位,当前的头放在数组里面。

实现:数组存的是引用,实际找的话就是找到引用对应的对象然后让这个对象的next指针,指向下一个节点。

---

加载因子。

看下put方法。

map的底层实现:https://www.cnblogs.com/dijia478/p/8006713.html

---

hashmap的属性:

看下这个方法:

10就是16。

左移一位就是*2。

hash方法:

hash算出序号的要求:

1.不越界

2.尽量均匀

为什么是2的n次方,可以保证的是-1之后1多。为什么-1,因为最大的下标是-1。

有什么高低位做异或运算,为了让高位和低位一起影响。

为什么异或会深远的影响呢?

举例:

1111与0101

与:0101不变高位不起作用

或:1111完全被高位控制

异或:1010扰动成功

---

key==null的问题。

addEntry:

---281---

扩容:p2

扩容:

扩容会翻倍的。

如何转移的呢?

 

扩容后还是原来的index或者index+旧数组的长度,前提是没有重新rehash。

---

两个线程同时扩容的情况呢?

两个线程同时进入这个方法:

内部生成这个数组。

老数组是一个每个线程都会建新的数组。

扩容就是创建新的数组然后全部转移。

假设第2个线程执行到了箭头就卡住了,第一个线程顺利执行完毕。

源头就是头插法的原因的。

为什么是2的n次幂:https://blog.csdn.net/apeopl/article/details/88935422

---

看下rehash:默认为false

什么是hash种子,什么时候为true。

---

这个会报错的。

看下源码:

这个是用迭代器的迭代方法。

看下remove得方法:

modCount是修改得次数。

正确得写法:

为什么:

modCount是快速失败的,记录的是操作的次数的。

两个线程一个遍历,一个删除就会快速失败。

------------------------------------------------

ConcurrentHashMap。

---

JDK7的concurrentHashMap:https://blog.csdn.net/Adrian_Dai/article/details/81429896

一个segment里面最小的是2个Entry数组。

扩容是单个segment扩容。

存segment数组的长度是固定的=线程安全数。

初始化时候有一个segment[0],存初始化信息,这样再new segment就不用再计算了。

 

---

unsafe方法:

var0是表示当前是哪个类使用的unsafe的。

平时用的unsafe必须用反射拿到的。

--

经典的代码:

package cn.itcast.n8.unsafe;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

public class Person {
    private int i=0;private static  sun.misc.Unsafe UNSAFE;private static long I_OFFSET;
    static{
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            UNSAFE = (Unsafe)field.get(null);
            I_OFFSET = UNSAFE.objectFieldOffset(Person.class.getDeclaredField("i"));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        Person person = new Person();
        new Thread(()->{
            while(true){
//                person.i++;
                boolean b = UNSAFE.compareAndSwapInt(person,I_OFFSET,person.i,person.i+1);
                if(b){
                    System.out.println(UNSAFE.getIntVolatile(person,I_OFFSET));
                }
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(()->{
            while(true){
//                person.i++;
                boolean b = UNSAFE.compareAndSwapInt(person,I_OFFSET,person.i,person.i+1);
                if(b){
                    System.out.println(UNSAFE.getIntVolatile(person,I_OFFSET));
                }
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

---282---

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值