为什么日期格式化类SimpleDateFormat是线程不安全的

>> 饿了么、美团外卖红包领取地址<<

在java中,格式化和解析时间我们常常会用到SimpleDateFormat这个类,但是这个类是线程不安全的,也即是说我们不能为了方便或者为了减小频繁创建SimpleDateFormat对象带来的内存开销而将其设置为类的静态变量供多个线程共享使用。

我们跟进SimpleDateFormat的format方法观察一下线程不安全的原因,format方法最终调用的代码如下:

// Called from Format after creating a FieldDelegate
private StringBuffer format(Date date, StringBuffer toAppendTo,
                            FieldDelegate delegate) {
    // Convert input date to time field list
    calendar.setTime(date);

    boolean useDateFormatSymbols = useDateFormatSymbols();

    for (int i = 0; i < compiledPattern.length; ) {
        int tag = compiledPattern[i] >>> 8;
        int count = compiledPattern[i++] & 0xff;
        if (count == 255) {
            count = compiledPattern[i++] << 16;
            count |= compiledPattern[i++];
        }

        switch (tag) {
        case TAG_QUOTE_ASCII_CHAR:
            toAppendTo.append((char)count);
            break;

        case TAG_QUOTE_CHARS:
            toAppendTo.append(compiledPattern, i, count);
            i += count;
            break;

        default:
            subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
            break;
        }
    }
    return toAppendTo;
}

可以看到方法的第一行就将传入的入参date表示的时间转成了Calendar类型,真正的日期格式化的操作在subFormat方法中使用calendar来获取时间(鉴于这个方法是真的长而且复杂,我就不研究也不粘贴了)。

假设我们的SimpleDateFormat对象是多个线程共享的,那么A线程刚设置了calendar的值,但是此时A线程还没有完成对时间的格式化操作,这时B线程过来了,由于这部分代码是没有加锁相关的操作,所以calendar的值会被B线程修改。这就导致了A线程最终格式化出来的时间是错误的。也就导致了线程不安全。


觉得内容还不错?打赏个钢镚鼓励鼓励!!👍

香蕉先生 安全套 避孕套 物理延时套 水润倍滑 成人情趣用品 物理延时10只装
¥9.80
喜宝莉 一次性加厚纯棉洗脸巾抽取式干湿两用母婴可用棉柔巾 单包60片
¥13.93
美加净轻香滋养手部身体乳护手霜 250ml 国际调香大师 告别干燥护手霜
¥45.50
墨斗鱼 大自然套装 香薰精油无火香薰精油补充液室内卫生间香薰炉灯卧室香水香氛复方植物精油
¥48.90
佳帮手擦玻璃神器双面清洗擦窗器家用伸缩杆窗户刮洗清洁工具 玻璃刮水
¥25.90
诺伯豪斯 口罩医用柳叶鱼型独立包装 时尚网红情侣口罩男女 含熔喷布医用口罩 夏花粉30枚
¥28.00
手护佳 一次性食品级丁腈手套 厨房家用公司复工学生开学劳保防护 盒装100只蓝色 L号
¥47.30
菲洛嘉 Filorga 水光精华7ml+水光面霜7ml+水光睡眠面膜7ml
¥42.00