ThreadLocal的和SimpleDateFormat的阵列(ThreadLocal and S

2019-09-19 04:27发布

使用非常类似于在描述的模式最近的问题 ,为多线程应用程序,我越来越怪异的日期值(例如,几年如2025年到2035年,当清楚地没有这样的价值在源数据存在)。 看来,并发问题正在发生。

源代码如下所示

// Various Java DateFormat patterns, e.g. "yyyy-MM-dd".
private static final String[] DATE_PATTERNS = new String[] {...};

private static SimpleDateFormat[] getFormats(final String[] patterns)
{
    ThreadLocal<SimpleDateFormat[]> LOCAL_FORMATS = new ThreadLocal<SimpleDateFormat[]>()
    {
        @Override
        protected SimpleDateFormat[] initialValue()
        {
            List<SimpleDateFormat> formatList = new ArrayList<SimpleDateFormat>();

            for (String pattern:patterns)
            {
                formatList.add(new SimpleDateFormat(pattern));
            }

            return formatList.toArray(new SimpleDateFormat[formatList.size()]);
        }
    };

    return LOCAL_FORMATS.get(); // Create a thread-local copy
}

private static final SimpleDateFormat[] DATE_FORMATS = getFormats(DATE_PATTERNS);

其静态初始化后, DATE_FORMATS阵列由许多类,后者又使用访问SimpleDateFormat数组对象解析或格式化几个日期字符串。

能有这样的使用场景任何并发的问题,尤其是考虑到使用ThreadLocal

Answer 1:

是的,有可能并发问题。 你的线程局部变量不会起任何作用。 当类初始化它只是使用的,用于临时存储的被立即检索并存储在静态常数日期格式的阵列。

所有线程,之后,一直使用的日期格式并发相同的情况下,不从任何线程局部变量得到他们。

该代码应相当是:

private static final String[] DATE_PATTERNS = new String[] {...};
private static final ThreadLocal<SimpleDateFormat[]> DATE_FORMATS = 
    new ThreadLocal<SimpleDateFormat[]>() {
        @Override
        protected SimpleDateFormat[] initialValue() {
            List<SimpleDateFormat> formatList = new ArrayList<SimpleDateFormat>();

            for (String pattern : DATE_PATTERNS)
            {
                formatList.add(new SimpleDateFormat(pattern));
            }

            return formatList.toArray(new SimpleDateFormat[formatList.size()]);
        }
    };

public static SimpleDateFormat[] getDateFormats() {
    return DATE_FORMATS.get();
}

我也将使用一个不可修改的List<SimpleDateFormat>而不是阵列,更安全。



Answer 2:

// Various Java DateFormat patterns, e.g. "yyyy-mm-dd".

格式“YYYY-MM-DD”很可能会给你奇怪的结果,因为“毫米”是分钟,而不是几个月。 根据JavaDoc:

M   Month in year   Month   July; Jul; 07
...
m   Minute in hour  Number  30


文章来源: ThreadLocal and SimpleDateFormat array