是否有一个好的线程安全的格式缓存库?

时间:2012-08-03 19:37:48

标签: java multithreading

我想在我的webapp中使用MessageFormat,DateFormat,DecimalFormat等进行一些格式化。

由于这些不是线程安全的,每次使用的一个静态实例都不起作用,但每次需要时都需要创建一个新的XXXXFormat对象。使用ThreadLocal缓存和重用它们似乎是一种明显的优化。

这似乎是一种非常常见的模式,所以我想知道是否有适当的库。

而不是打电话:

    DecimalFormat formatter = new DecimalFormat("###,##0.00");

    String formatted = formatter.format(value);             
每次我需要格式化时,为什么不:

    String formatted = FormatCache.formatDecimal("###,##0.00",numberValue);

哪里FormatCache会使用格式模式上键入的HashMap进行ThreadLocal缓存?

据推测,还有其他方法,如:

    String FormatCache.formatDecimal(String, Number);
    String FormatCache.formatDate(String, Date);
    String FormatCache.formatMessage(String, Object...);

3 个答案:

答案 0 :(得分:5)

Apache Commons LangFastDateFormat,它以正确的方式解决问题(在我看来),只是以线程安全开头:

  

FastDateFormat是SimpleDateFormat的快速且线程安全的版本。

     

在大多数格式化情况下,此类可用作SimpleDateFormat的直接替换。此类在多线程服务器环境中特别有用。 SimpleDateFormat在任何JDK版本中都不是线程安全的,也不会像Sun关闭bug / RFE那样。

答案 1 :(得分:4)

TL;博士

缓存线程安全DateTimeFormatter 对象(不可变)。

从不使用SimpleDateFormat仅使用 java.time 包进行日期工作。

java.time

麻烦的旧日期时间类,例如DateFormat& SimpleDateFormat现在已被现代 java.time 类取代。具体来说,就是DateTimeFormatter类。

不可变对象,线程安全

java.time 类设计为Immutable Objects。这意味着不是修改对象中的任何内容,而是生成新的不同对象。原件保持不变。

这个和其他技术通过设计制作了 java.time thread-safe,并且是如此记录的。

DateTimeFormatter

DateTimeFormatter dateTimeFormatterFullQuébec = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;

您可以缓存该对象dateTimeFormatterFullQuébec,并将其保留。

ZoneId

同样,您可以保留ZoneId时区对象的缓存。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId zoneMontréal = ZoneId.of( "America/Montreal" ) ;

然后随时使用它们,甚至跨线程。

ZonedDateTime zdt = ZonedDateTime.now( zoneMontréal ) ;
String output = zdt.format( dateTimeFormatterFullQuébec ) ;
  

dimanche 4 mars2018à18:36:32东部标准时间

java.time 对象(例如ZonedDateTimeInstant)也是不可变且线程安全的,就像ZoneId& DateTimeFormatter。您可以缓存所有这些,并在线程中使用它们。

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 2 :(得分:2)

你应该对这样的事情非常小心。标准(简单)格式化程序不是线程安全的。我与一些共享/缓存的格式化程序遇到了一些多线程相关的问题,但那是几年前(Java 1.4)。如果您检查JavaDocs(SimpleDateFormat),您会注意到以下内容:

  

同步

     

日期格式未同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问格式,则必须在外部进行同步。