开发者

Confusion about thread safety - SimpleDateFormat example

开发者 https://www.devze.com 2023-02-24 04:42 出处:网络
I have a question about thread safety.From what I have been told, SimpleDateFormat is not thread safe.I was wondering what effects it would have if I use it the following way in my spring controller:

I have a question about thread safety. From what I have been told, SimpleDateFormat is not thread safe. I was wondering what effects it would have if I use it the following way in my spring controller:

private final static SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd yyyy", Locale.US);

Later in my of my controller functions I use it as follows:

  try {
        changedate = changedate.substring(0, 15);                                                
        calcDate = dateFormat.parse(changedate);
    } catch (ParseException e2) {
        logger.error("Date Parsing Problem", e2); 
    }

calcDate then gets added to my model object and a ModelAndView is returned.

So what kind of problems will I see using it this way? Would simply removing the static keyword fix any issues because then each thread will use its own instance of dateFormat? Any clarity on this subejct in regards to thread safety would be much appreci开发者_如何学Cated.

Thanks


SimpleDateFormat.parse() uses an instance variable called calendar to build the date from the string. If two threads try to parse at the same time, the calendar variable will get clobbered and you'll get wrong results.

Making the variable not static won't necessarily help, since two threads could still be using the same controller. A better solution is to either create a new DateFormat object each time you parse a date, or use thread local storage. Better still, use JodaTime which has thread safe parsers.


So what kind of problems will I see using it this way?

Developers of SimpleDateFormat took a very strange decision - during work of parse() they store partially parsed date in a field of SimpleDateFormat. Obviously, it means that you can't call parse() from several threads simultaneously.

Would simply removing the static keyword fix any issues because then each thread will use its own instance of dateFormat?

Removing static won't help you, since Spring controllers are singleton scoped by default, so Spring uses a single instance of your controller to serve all requests.


Personally, I would avoid all these issues by just using JodaTime. The API is much richer, it doesn't have the threading issues, and it's a lot faster.


SimpleDateFormat has instance-wide state while parsing and is therefore not thread safe. If you use it from multiple threads it will crash (well like java crashes :-), no process crash and the like). Removing static keyword doesn't necessarily cure the problem because it depends on the instance and it still might be used from several threads.

You can create a local instance within the method above so that each parsing happens with its own formatter or play with threadlocal variables.


Not sure what type of problems you would see if you did it this way. But the Javadocs warn against concurrent access to the SimpleDateFormat and the way your using it would definetly involve concurrent access. Removing the static would not eliminate the concurrency problem unless you were implementing some type of synchronization policy for the enclosing class or otherwise preventing multiple threads from accessing the class.

You could try to create a SimpleDateFormat for each thread by instantiating it within the body of a method and ensuring that the reference to SimpleDateFormat never "escapes" the method. In other words, declare the variable, instantiate the object, and use the object within the same method. This would ensure that the reference for that SimpleDateFormat would be removed when the method exits.


Android Developers can use the safe (thread localised) wrappers around SimpleDateFormat that are in: org.apache.http.impl.cookie.DateUtils

  • http://developer.android.com/reference/org/apache/http/impl/cookie/DateUtils.html

The source code for the implementation is here (e.g. FROYO API Level 8):

  • https://android.googlesource.com/platform/external/apache-http/+/android-2.2_r1/src/org/apache/http/impl/cookie/DateUtils.java


Another way is, if you can ensure each time when your controller is called, you return a new instance, then remove the static reference.

0

精彩评论

暂无评论...
验证码 换一张
取 消