【问题标题】:Java ResultSet.getTimestamp using Calendar & Thread safety使用日历和线程安全的 Java ResultSet.getTimestamp
【发布时间】:2013-07-30 17:36:22
【问题描述】:

我的要求: 从数据库 ResultSet 中获取时间戳(以 UTC 格式存储)并以线程安全的方式进行。

我的代码目前如下所示:

Calendar utcCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
while(rs.next())
    rs.getTimestamp("utctime",utcCal);

...按预期工作;然而,为每个查询创建一个新的 Calendar 对象似乎相当昂贵(它们非常频繁)。

我一直在寻找 Joda-time 作为可能的替代品,但不能完全弄清楚如何用 Joda-time 线程安全对象替换日历。最好创建一个所有查询都可以使用的静态最终 Joda-Time 线程安全日历替换。

对于成本更低的结果集迭代有什么想法吗?由于日历不是线程安全的,我不能使用单个共享实例。

【问题讨论】:

  • 为什么不使用常量作为第二个参数?
  • 什么常数?我不能使用 Calendar 作为常量,因为它不是线程安全的。编辑:我想我明白你的意思——调整后的问题

标签: java multithreading calendar thread-safety jodatime


【解决方案1】:

使用synchronized 关键字?

        synchronized (CALENDAR) {
        CALENDAR.setTimeInMillis(System.currentTimeMillis());
        while(rs.next()){
            rs.getTimestamp("utctime", CALENDAR);
            //rest of code
        } 
    }

【讨论】:

  • 我认为这会造成太多的瓶颈,因为会有很多线程同时运行这个方法——等待锁释放的成本可能会更高(及时) 而不是为每个查询创建一个新的日历实例。
【解决方案2】:

您可以使用ThreadLocal<Calendar>。这样,每个线程都会有自己独特的 Calendar 实例:

public static final ThreadLocal<Calendar> RESULT_SET_CALENDAR = new ThreadLocal<Calendar>() {
    @Override 
    protected Calendar initialValue() {
        Calendar calendar = Calendar.getInstance();
        // set appropriate timezone
        return calendar;
    }
};

while (rs.next()) {
    Timestamp timestamp = rs.getTimestamp("utctime", RESULT_SET_CALENDAR.get());
    ...
}

也就是说,与执行 SQL 查询所需的时间相比,我不确定每次创建新日历的成本是否如此之高。我的猜测是,如果有的话,您将获得微不足道的性能提升。

【讨论】:

  • 你是对的,这不是一个巨大的成本,但它仍然让我感到困扰,原生日历不是线程安全的,即使对其执行简单的“获取”也会导致它发生变异。
猜你喜欢
  • 1970-01-01
  • 2011-09-08
  • 2010-10-12
  • 1970-01-01
  • 2015-05-16
  • 2012-06-19
  • 2014-03-31
  • 1970-01-01
  • 2023-03-27
相关资源
最近更新 更多