ThreadLocal for multithreaded access to SimpleDate

2019-07-09 00:55发布

问题:

I have a number of Java date patterns and want to reuse them multiple times in SimpleDateFormat objects across different threads, via static references, for speed.

The code would look something like this (inside a class called, say, FormatClass):

private static String[] PATTERNS = new String[] {...};

public 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[0]);
    }
}

Using the above code, a method on another class could format (or parse) multiple date strings as follows:

public static void printFormatted(String date)
{
    for (SimpleDateFormat sdf:FormatClass.LOCAL_FORMATS.get())
    {
        System.out.println(sdf.format(date));
    }
}

where the printFormatted() method may or may not be static, but will definitely be accessed by multiple different threads.

Will the above approach work as expected?

回答1:

To answer to your question straightly : yes, every thread will have their own unique copy as recommended in the doc of SimpleDateFormat.



回答2:

It looks pretty good, but you can easily test it with a multi-threaded program. Just print the Id of the thread (Thread.currentThread().toString()) and System.identifyHashCode(simpleDateFormat) and verify that you are getting unique copies for each thread and appropriately reusing them.



回答3:

This works well but the code is relatively complex. I would propose to check maybe you can assign the SimpleDateFormat to some local variable inside the method (always thread local). This works well when many values are formatted in a loop that then can be inside the same method.



回答4:

I think there's a more elegant approach that no one has proposed yet -- just create a drop-in replacement wrapper class for SimpleDateFormat that synchronizes access to its methods. In most situations, I would argue that the synchronization overhead is no worse than the hash lookup in ThreadLocalMap.