ConcurrentHashMap详解与Unsafe使用

先来说说Unsafe吧,它的全类名是sun.misc.Unsafe,这是一个java不推荐的编程使用的类,只在源码中使用,它的构造方法被私有化了,不能去new,但是有一个getUnsafe方法:

@CallerSensitive
    public static Unsafe getUnsafe() {
   
        Class var0 = Reflection.getCallerClass();
        if (var0.getClassLoader() != null) {
   
            throw new SecurityException("Unsafe");
        } else {
   
            return theUnsafe;
        }
    }

该方法表示,拿到当前类的类加载器,如果该类加载器是BootClassLoader,那么就会返回null ,才会返回unsafe对象,我们创建的类一般是AppClassLoader,而不是BootClassLoader,所以使用这个方法会抛出异常,那怎么使用这个类呢?,下面是一个小案例

public class JDK7ConcurrtHashMap {
   
    public static void main(String[] args) {
   
        Unsafe unsafe = Person.getUnsafe();
        int si = unsafe.arrayIndexScale(String[].class);
        int offset = unsafe.arrayBaseOffset(String[].class);
        System.out.println(unsafe.getObjectVolatile(Person.names, offset + si * 0));


        //
        ConcurrentHashMap<String,String> cHashMap = new ConcurrentHashMap<String, String> ();
        cHashMap.put("biozzo", "nice~");
    }

    static class Person{
   
        private static int i = 0;
         static Field f;
         static String[] names = new String[]{
   "biozzo","kevin","can"};

        private static  Unsafe unsafe;

        static {
   
            try {
   
                f = Unsafe.class.getDeclaredField("theUnsafe");
                f.setAccessible(true);
                unsafe = (Unsafe) f.get(null);
            } catch (NoSuchFieldException | IllegalAccessException e) {
   
                e.printStackTrace();
            }
        }

        static Unsafe getUnsafe(){
   
            return unsafe;
        }
    }
}

直接通过反射拿到属性就可以了,这个小案例展示了一个通过使用Unsafe得到数组值得方法,就像是寻址一样,si是步长,offset是偏移量,通过这样就可以拿到数组中的值。

我们再来看ConcurrentHashMap的构造方法:

public ConcurrentHashMap(int initialCapacity,
                             float loadFactor, int concurrencyLevel) {
   
        if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
            throw new IllegalArgumentException();
        if (concurrencyLevel > MAX_SEGMENTS)
            concurrencyLevel = MAX_SEGMENTS;
        // Find power-of-two sizes best matching arguments
        int sshift = 0;
        int ssize = 1;
        while (ssize < concurrencyLevel) {
   
            ++sshift;
            ssize <<= 1;
        }
        this.segmentShift = 32 - sshift;
        this.segmentMask = ssize - 1;
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        int c = initialCapacity / ssize;
        if (c * ssize < initialCapacity)
            ++c;
        int cap = MIN_SEGMENT_TABLE_CAPACITY;
        while (cap < c)
            cap <<= 1;
        // create segments and segments[0]
        Segment<K,V> s0 =
            new Segment<K,V>(loadFactor, (int)(cap * loadFactor),
                             (HashEntry<K,V>[])new HashEntry[cap]);
        Seg
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值