且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

为什么 Java 的 SimpleDateFormat 不是线程安全的?

更新时间:2022-03-03 08:23:50

SimpleDateFormat 将中间结果存储在实例字段中.因此,如果一个实例被两个线程使用,它们可能会混淆彼此的结果.

SimpleDateFormat stores intermediate results in instance fields. So if one instance is used by two threads they can mess each other's results.

查看源代码显示有一个Calendar实例字段,用于DateFormat/SimpleDateFormat代码>.

Looking at the source code reveals that there is a Calendar instance field, which is used by operations on DateFormat / SimpleDateFormat.

例如parse(..)首先调用calendar.clear(),然后calendar.add(..).如果另一个线程在第一次调用完成之前调用 parse(..),它将清除日历,但另一个调用将期望它填充有计算的中间结果.

For example parse(..) calls calendar.clear() initially and then calendar.add(..). If another thread invokes parse(..) before the completion of the first invocation, it will clear the calendar, but the other invocation will expect it to be populated with intermediate results of the calculation.

在不牺牲线程安全性的情况下重用日期格式的一种方法是将它们放在 ThreadLocal 中 - 有些库会这样做.如果您需要在一个线程中多次使用相同的格式.但如果您使用的是 servlet 容器(具有线程池),请记住在完成后清理线程本地.

One way to reuse date formats without trading thread-safety is to put them in a ThreadLocal - some libraries do that. That's if you need to use the same format multiple times within one thread. But in case you are using a servlet container (that has a thread pool), remember to clean the thread-local after you finish.

老实说,我不明白他们为什么需要实例字段,但事实就是这样.您还可以使用 joda-time DateTimeFormat 这是线程安全的.

To be honest, I don't understand why they need the instance field, but that's the way it is. You can also use joda-time DateTimeFormat which is threadsafe.