SimpleDateFormat线程不安全分析

好早之前总结的,测试代码找不到了,应该是在一个多线程无锁环境下使用同一个SimpleDateFormat对日期进行格式化,报错的错误。

SimpleDateFormat包含numberFormat字段,他是DecimalFormat类型,
DecimalFormat内部有个digitList是java.text.DigitList类型,
SimpleDateFormat的parse方法会转调DecimalFormat的parse方法,在DecimalFormat的parse方法内部有:longResult = digitList.getLong();这段代码,

DigitList的getLong
public final long getLong() {
    // 省略部分  ... ...
    StringBuffer temp = getStringBuffer();
    temp.append(digits, 0, count); // 这个地方的count是个字段
    for (int i = count; i < decimalAt; ++i) {
        temp.append('0');
    }
    // 这一行抛出的异常, 推断temp是空字符串, 联系上下文代码进一步推断count=0, 猜测count被并发修改了,那应该在parse方法的longResult = digitList.getLong()这段代码之前有地方修改了count
    return Long.parseLong(temp.toString()); 
}

在DecimalFormat的parse方法中:
public Number parse(String text, ParsePosition pos) {
        ... ...
        if (!subparse(text, pos, positivePrefix, negativePrefix, digitList, false, status)) { // line: 1249
        ... ...
        }
        
        
        if (digitList.fitsIntoLong(status[STATUS_POSITIVE], isParseIntegerOnly())) {
            ... ...
            longResult = digitList.getLong();  // line: 1297 
            ... ...
        } 
}

subparse方法如下:
private final boolean subparse(String text, ParsePosition parsePosition,
                   String positivePrefix, String negativePrefix,
                   DigitList digits, boolean isExponent,
                   boolean status[]) { 
                   
        ... ...
        if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0, symbols.getInfinity().length())) {
            ... ...
        } else {
            // 这里修改了digits的count [注意: subparse倒数第三个实参名是digitList,而形参名是digits]
            digits.decimalAt = digits.count = 0;  // line: 1431 
            ... ...
}   

你可能感兴趣的:(SimpleDateFormat线程不安全分析)