zoukankan      html  css  js  c++  java
  • 动态生成Long类型数据不能作synchronized锁对象的解决方法(String中intern()方法的使用)

    在前期系统开发中,系统升级成了区域版本的,一个系统拥有多个机构,机构ID字段是字符串类型的,在java中由于字符串可以缓存在常量池中,之前都是用机构ID作为锁条件的,这样可以保证,同一个机构是串行的而不同机构是并行的。

    最近使用新框架,机构ID由String类型升级成了Long类型,这样再直接使用机构ID作synchronized的锁对象肯定是不行的,因为并没有常量池来缓存Long类型数据,不过跟Integer类型一样,Long类型自身也是做了缓存的:

    public static Long valueOf(long l) {
            final int offset = 128;
            if (l >= -128 && l <= 127) { // will cache
                return LongCache.cache[(int)l + offset];
            }
            return new Long(l);
        }
    

    可以看到缓存区域也是[-128,127],在这个区域内使用栈赋值的方式声明变量,可以保证引用地址是同一个,超过这个区域就不行了,我不能保证机构ID只在这个范围内啊,怎么解决呢?
    首先想到的就是把机构ID重新转成字符串,不就行了吗。
    Long.toString方法源码:

     public static String toString(long i) {
            if (i == Long.MIN_VALUE)
                return "-9223372036854775808";
            int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
            char[] buf = new char[size];
            getChars(i, size, buf);
            return new String(buf, true);
        }
    

    可以看到,他每次返回的都是一个new出来的字符串对象,这样锁对象就变了,是锁不住的。这个时候String的intern方法就出场了。

    在jdk1.6中,该方法把字符串的值复制到常量区,然后返回常量区里这个字符串的值;
    在jdk1.7里,该方法在常量区记录该字符串首次出现的实例引用,然后返回该地址,常量区可以保存字面量也可以保存字符串对象在堆中的引用。
    因为jdk7中intern方法是(在常量区找不到该字符串时)将该字符串对象在堆里的引用注册到常量区,以后使用相同字面量(双引号形式)声明的字符串对象都指向该地址,也就是该字符串在堆中的地址。用代码说明一下:

    public static void main(String[] args) {
            String str1 = new String("abc");
            String str2 = (new String("a") + new String("bc"));
            System.out.println(str1 == str2);// false
            System.out.println(str1.intern() == str2.intern());// true
        }
    

    上面的str1和str2地址肯定是不相同的,但是用于字面量是相同的所以,intern方法的返回值再比较就是相同的啦,这样问题就就解决了:

    Long jiGouId = Loginutils.currentDoneOrgId();
    String lockCondition = Long.toString(jiGouId).intern();
    synchronized (lockCondition) {
    	// dosomething
    }
    
    一颗安安静静的小韭菜。文中如果有什么错误,欢迎指出。
  • 相关阅读:
    C# 图片存入SQL Server数据库
    C#如何将Build成功的程序集Copy到上一层目录
    JavaScript中JSON字符串和JSON对象相互转化
    如何将C#对象转化为JSON字符串
    SQL的常用语句
    NHibernate的使用
    如何配置Spring的XML文件及使用
    TRIGGER的使用(修改SP自动触发)
    iOS UIButton上下排列(上图下文)
    将.c .h文件打包成静态库 .a .so
  • 原文地址:https://www.cnblogs.com/c-Ajing/p/13448364.html
Copyright © 2011-2022 走看看