gpt4 book ai didi

java - 使 SimpleDateFormat 线程安全

转载 作者:塔克拉玛干 更新时间:2023-11-01 23:01:17 25 4
gpt4 key购买 nike

我有许多线程处理 Trade 对象,其中我使用 RowMapper 将数据库列映射到 Trade 对象。

我知道 SimpleDateFormat 在任何 Java 中都不是线程安全的。结果,我在 startDate 中得到了一些不可预测的结果。例如,我在 endDate 中也看到了 startDate 的日期。

这是我的代码:

public class ExampleTradeMapper {

private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MMM-yyyy");

public void map(Trade trade, ResultSet rs, int rowNum) throws SQLException {

trade.setStartDate(getFormattedDate(rs.getDate("START_DATE")));
trade.setEndDate(getFormattedDate(rs.getDate("END_DATE")));
trade.setDescription(rs.getString("DESCRIPTION"));

}

private String getFormattedDate(Date date) {
try {
if (date != null)
return DATE_FORMAT.format(date).toUpperCase();
else
return null;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

}


public class SomeRowMapper extends TradeMapper implements RowMapper<Trade> {

@Override
public Trade mapRow(ResultSet rs, int rowNum) throws SQLException {

Trade trade = new Trade();

map(trade, rs, rowNum);

return trade;
}
}

对于这个应用程序,我的核心池大小约为 20,最大约为 50。这些线程有时可以处理来自数据库的大约 100 条交易记录。

使此日期格式化线程安全的最佳方法是什么?我应该使用 FastDateFormat 直接替换吗?

有没有更好的替代方法来使这个线程安全?

最佳答案

tl;博士

不要使用字符串,而是使用通过 JDBC 4.2 或更高版本与数据库交换的 java.time 对象(特别是 LocalDate)。

myResultSet.getObject(      // Exchange modern java.time objects with your database.
"START_DATE" ,
LocalDate.class
) // Returns a `LocalDate` object.
.format( // Generate a `String` representing textually the content of this `LocalDate`.
DateTimeFormatter.ofPattern( "dd-MMM-uuuu" , Locale.US )
)

23-Jan-2018



作为不可变对象(immutable对象),java.time 对象在设计上是线程安全的。您可以缓存 java.time 对象以跨线程使用。

时间

Making SimpleDateFormat thread safe



别。

使用现代 java.time 类,这些类多年前取代了麻烦的旧的遗留日期时间类,例如 SimpleDateFormatjava.util.Datejava.sql.DateCalendar

java.time 类被设计为线程安全的。他们使用 immutable objects 模式,根据原始值返回新对象,而不是“变异”(改变)原始值。

使用智能对象,而不是哑弦

我认为没有理由在您的示例代码中使用字符串:不在您的数据库访问代码中,不在您的业务对象 ( Trade ) 中。

JDBC

从 JDBC 4.2 开始,我们可以与数据库交换 java.time 对象。对于类似于 SQL 标准 DATE 类型的数据库列,请使用类 LocalDate LocalDate 类表示没有时间和时区的仅日期值。
myPreparedStatement.setObject( … , myLocalDate ) ;

恢复。
LocalDate myLocalDate = myResultSet.getObject( … , LocalDate.class ) ;

业务对象

您的 Trade 类应该将成员变量 startDateendDate 保存为 LocalDate 对象,而不是字符串。
public class Trade {
private LocalDate startDate ;
private LocalDate endDate ;


// Getters
public LocalDate getStartDate() {
return this.startDate ;
}
public LocalDate getEndDate() {
return this.endDate;
}
public Period getPeriod() { // Number of years-months-days elapsed.
return Period.between( this.startDate , this.endDate ) ;
}

// Setters
public void setStartDate( LocalDate startDateArg ) {
this.startDate = startDateArg ;
}
public void setEndDate( LocalDate endDateArg ) {
this.endDate = endDateArg ;
}

@Override
public toString() {
"Trade={ " + "startDate=" + this.startDate.toString() …
}

}

不需要字符串,不需要格式化模式。

字符串

要将日期时间值交换或存储为文本,请使用标准 ISO 8601 格式而不是您的问题中看到的自定义格式。

java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。所以不需要指定格式模式。
LocalDate ld = LocalDate.parse( "2018-01-23" ) ; // January 23, 2018.
String s = ld.toString() ; // Outputs 2018-01-23.

为了在用户界面中呈现,让 java.time 自动本地化。要本地化,请指定:
  • FormatStyle 确定字符串的长度或缩写。
  • Locale 来确定:
  • 用于翻译日名、月名等的人类语言。
  • 决定缩写、大小写、标点符号、分隔符等问题的文化规范。

  • 例子:
    Locale l = Locale.CANADA_FRENCH ; 
    DateTimeFormatter f =
    DateTimeFormatter.ofLocalizedDate( FormatStyle.FULL )
    .withLocale( l ) ;
    String output = ld.format( f ) ;

    mardi 23 janvier 2018


    DateTimeFormatter 类在设计上是线程安全的,作为不可变对象(immutable对象)。您可以持有一个跨线程使用的实例。

    关于 java.time

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

    Joda-Time 项目,现在在 maintenance mode 中,建议迁移到 java.time 类。

    要了解更多信息,请参阅 Oracle Tutorial 。并在 Stack Overflow 上搜索许多示例和解释。规范是 JSR 310

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

    从哪里获得 java.time 类?
  • Java SE 8Java SE 9Java SE 10 和更高版本
  • 内置。
  • 具有捆绑实现的标准 Java API 的一部分。
  • Java 9 添加了一些小功能和修复。
  • Java SE 6Java SE 7
  • ThreeTen-Backport 中,大部分 java.time 功能被反向移植到 Java 6 和 7。
  • Android
  • 更高版本的 Android 捆绑实现 java.time 类。
  • 对于早期的Android(<26),ThreeTenABP 项目适配了ThreeTen-Backport(上面提到过)。见 How to use ThreeTenABP…

  • ThreeTen-Extra 项目使用附加类扩展了 java.time。该项目是 future 可能添加到 java.time 的试验场。您可能会在这里找到一些有用的类,例如 Interval YearWeek YearQuarter more

    关于java - 使 SimpleDateFormat 线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51366289/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com