关于 SimpleDateFormat 线程安全

在开发的额过程中突然遇到关于 SimpleDateFormat 线程安全的问题,在此记录一下:

开始我并没有注意到 SimpleDateFormat 的线程安全问题,所以将它设置为类的共有属性,想着图个方便,懒得每次使用都要新建一个对象,于是我也就这么做了。因为是开发环境,最初的时候自己也没有察觉出什么异常,直到我的 web 前端使用each 方法,然后便出现了莫名的状况,后端的捕获的异常出现在 SimpleDateFormat 这儿。刚刚出现这个问题时,我没有在意,因为之前运行得好好的,这里应该没啥问题,所以开始时也没有往线程方面去想。然后我去检查是哪儿弄错了,在调试过程中,我发现这一块时好时坏,然后我就察觉到了坏味道,这种随机出现的问题,一般都与多线程有关;然后我便去查我的代码,发现了问题所在:前端使用 each 对选中的数据进行遍历,并发送异步请求,也就是说这里我为后端多个线程访问公共资源 SimpleDateFormat 创建了条件(当然咯,这是开发环境,如果是生产环境,那就与这里没啥干系了,主要问题还是在公共资源的访问上面),而 SimpleDateFormat 又不是线程安全的,所以造成了错误。

SimpleDateFormat 是非线程安全的,主要在问题在calendar共有资源的访问(好吧,这是一句废话)

    // 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;
    }

总结:
① 前端 each 方法是异步的,使用需注意。
② 后端使用 SimpleDateFormat 需要注意线程安全的问题,至于解决无非两种方式:加锁 和 创建新的对象,当然也可以使用 ThreadLocal 来解决,不过它本质上还是创建了一个新的对象。

你可能感兴趣的:(问题及解决)