MENU

随笔

May 15, 2022 • 学习笔记

多线程并发

多线程下的Random随机数

避免 Random 实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一 seed 导致的性能下降。JDK7推荐ThreadLocal优化,JDK7推荐使用ThreadLocalRandom。

SimpleDateFormat 和 DatetimeFormatter

SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,必须加锁,或者使用ThreadLocal,或者使用 DateUtils 工具类。如果是 JDK8 的应用,可以使用 instant 代替 Date,Localdatetime 代替 Calendar, Datetimeformatter 代替 Simpledateformatter。

双重检查锁和volatile关键字

双重检查锁的问题:初始化Singleton 和 将对象地址写到instance字段 的顺序是不确定的。在某个线程new Singleton()时,在构造方法被调用之前,就为该对象分配了内存空间并将对象的字段设置为默认值。此时就可以将分配的内存地址赋值给instance字段了,然而该对象可能还没有初始化;此时若另外一个线程来调用getInstance,取到的就是状态不正确的对象。

在jdk1.5之后的版本中,可以将instance设置为volatile使双重检查锁生效。

public class Singleton {
    private static volatile Singleton instance = null;
    private Singleton(){}

    public static Singleton getInstance() {
       if(instance == null) {
           synchronized(Singleton.class) {
              if(instance == null) {
                  instance = new Singleton();
              }
           }
       }
       return instance;
    }
}

Mybaits

{} 和 ${}的区别

​ #{ }是预编译处理,MyBatis在处理#{ }时,它会将sql中的#{ }替换为?,然后调用PreparedStatement的set方法来赋值,传入字符串后,会在值两边加上单引号

​ ${ }是字符串替换, MyBatis在处理${ }时,它会将sql中的${ }替换为变量的值,传入的数据不会加两边加上单引号。

​ 使用${ }会导致sql注入,不利于系统的安全性!

杂项

包装类型缓存问题

        Integer a = 1228;
        Integer b = 1228;
        System.out.println(a == b);         //false
        System.out.println(a.equals(b)); //true

Equals判定

使用Equals判定时应将常量放在前面,变量放在后面。

if(CONSTANT_A.equals("AAA")){
}

JDK7之后推荐使用Objects.equals()方法。Objects.equals()逻辑如下:

    public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }

浮点数和BigDecimal

浮点数在计算机中是无法精确表示的,如遇到货币等精确值时应使用BigDecimal

构造BigDecimal参数时应使用String,而非double或float类型,如应使用new BigDecimal("0.005")而不是new BigDecimal(0.005)

资金类运算,一般情况下,应以加、减法为主,慎用乘、除法。并注意核对,防止误差,保持账平。例如:“将100.00平分3份”的场景,若每份33.33的话,会有误差

Bean Validation 中内置的校验规则

Hibernate Validator

注解作用
@CreditCardNumber(ignoreNonDigitCharacters=)被注释的字符串必须通过 Luhn 校验算法,银行卡,信用卡等号码一般都用 Luhn 计算合法性
@Currency(value=)被注释的 javax.money.MonetaryAmount 货币元素是否合规
@DurationMax(days=, hours=, minutes=, seconds=, millis=, nanos=, inclusive=)被注释的元素不能大于指定日期
@DurationMin(days=, hours=, minutes=, seconds=, millis=, nanos=, inclusive=)被注释的元素不能低于指定日期
@EAN被注释的元素是否是一个有效的 EAN 条形码
@Length(min=, max=)被注释的字符串的大小必须在指定的范围内
@LuhnCheck(startIndex= , endIndex=, checkDigitIndex=, ignoreNonDigitCharacters=)Luhn 算法校验字符串中指定的部分
@Mod10Check(multiplier=, weight=, startIndex=, endIndex=, checkDigitIndex=, ignoreNonDigitCharacters=)Mod10 算法校验
@Mod11Check(threshold=, startIndex=, endIndex=, checkDigitIndex=, ignoreNonDigitCharacters=, treatCheck10As=, treatCheck11As=)Mod11 算法校验
@Range(min=, max=)被注释的元素必须在合适的范围内
@SafeHtml(whitelistType= , additionalTags=, additionalTagsWithAttributes=, baseURI=)classpath中要有jsoup包
@ScriptAssert(lang=, script=, alias=, reportOn=)检查脚本是否可运行
@URL(protocol=, host=, port=, regexp=, flags=)被注释的字符串必须是一个有效的url