【问题标题】:Is Java's TimeZone thread-safe?Java 的 TimeZone 是线程安全的吗?
【发布时间】:2010-12-16 02:52:06
【问题描述】:

我希望我的应用程序只有一个 TimeZone 对象,它将被来自其他地方的许多 SimpleDateFormat 和 Calendar 对象同时使用。这是为了避免必须总是做TimeZone.getTimeZone(ID)。

我知道SimpleDateFormat 和Calendar 类不是线程安全的,这就是为什么我将一个线程配置为始终创建它们的新实例。但是TimeZone 呢?我不清楚我是否可以安全地执行以下操作:

final TimeZone tz = TimeZone.getTimeZone("GMT");
...
//Thread 1.
Thread t1 = new Thread(Runnable(){
    public void run()
    {
        Calendar cal = Calendar.getInstance(tz);
        ...
        SimpleDateFormat sdf = new SimpleDateFormat();
        sdf.setTimeZone(tz);
        ...
    }
});
t1.start();
...
//Thread 2.
Thread t2 = new Thread(Runnable(){
    public void run()
    {
        Calendar cal = Calendar.getInstance(tz);
        ...
        SimpleDateFormat sdf = new SimpleDateFormat();
        sdf.setTimeZone(tz);
        ...
    }
});
t2.start();
...

谢谢!

【问题讨论】:

    标签: java timezone thread-safety


    【解决方案1】:

    我看了一遍它的源代码,得出的结论不是。

    查看JodaTime timezone 类。它在 javadoc 中说它是线程安全且不可变的。

    【讨论】:

    • 我看到 TimeZone.getDefault() 在多线程环境中经常挂起。
    【解决方案2】:

    不是。

    而且你不需要它。您的代码将其用作:

    final TimeZone tz = TimeZone.getTimeZone("GMT");
     ......
    // thread 1 SimpleDateFormat instance
    sdf.setTimeZone(tz);
    
    // thread 2 SimpleDateFormat instance
    sdf.setTimeZone(tz);
    

    您有两个线程使用相同的时区,但由于您没有对其进行修改,因此您不需要它是线程安全的。

    你唯一可以修改的是ID,但即使那样你也可以,因为其余的属性都是只读的

    您遇到麻烦的唯一方法是更改​​ id 并将您自己缓存到时区,如果您总是从 TimeZone.getTimeZone() 获取它,那么您也是安全的,因为该方法 is 线程安全。

    【讨论】:

      【解决方案3】:

      没有明确的文档表明 TimeZone 是线程安全的,因此最安全的方法是假设它不是线程安全的。

      TimeZone 类有两个实例变量,与 ID 及其 GMT 偏移量有关。常识会说 Calendar.getInstance 和 SimpleDateFormat 没有修改 TimeZone 对象状态的业务(在第一种情况下,它被用作查找键,在第二种情况下,用作格式化上下文)。

      常识或确定性 - 你的选择。

      【讨论】:

        【解决方案4】:

        您没有修改您的 TimeZone,因此您的代码应该是线程安全的,无论 TimeZone 的底层实现是否是线程安全的(静态方法除外,例如 (getTimeZone/getDefault/setDefault)。

        【讨论】:

        【解决方案5】:

        这似乎没问题。如果您依赖 TimeZone.getDefault() 那将是另一回事。因为另一个线程可能正在调用 TimeZone.setDefault()。

        【讨论】:

        • 实际上,这会是安全的。 TimeZone.getDefault() 和 TimeZone.setDefault() 获取并设置线程本地默认值。看看源代码吧!
        • @StephenC - 不,它不安全。请看stackoverflow.com/questions/2176784/…
        猜你喜欢
        • 2011-03-07
        • 1970-01-01
        • 1970-01-01
        • 2016-08-24
        • 2019-04-23
        • 2012-04-07
        • 2011-12-09
        相关资源
        最近更新 更多