Java的时区是否线程安全?

18

我希望应用程序只有一个TimeZone对象,可以被其他地方并发使用的许多SimpleDateFormatCalendar对象所使用。这是为了避免总是执行TimeZone.getTimeZone(ID)

我知道SimpleDateFormatCalendar类不是线程安全的,这就是为什么我配置一个线程始终创建它们的新实例。但是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();
...

谢谢!

5个回答

7
我曾经查看了它的源代码,并得出结论它不是线程安全的。
查看JodaTime时区类。它在javadoc中说它是线程安全和不可变的。

1
我曾经在多线程环境中频繁看到 TimeZone.getDefault() 函数出现卡顿的情况。 - Martin

6

不是。

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

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

// thread 2 SimpleDateFormat instance
sdf.setTimeZone(tz);

你有两个线程使用相同的时区,但由于你没有修改它,所以不需要使其具备线程安全性。
唯一可以修改的是ID,但即使如此,对于其余属性都是只读的,因此也没问题。
唯一可能会出现问题的方式是更改ID并自行缓存时区。如果你总是从TimeZone.getTimeZone()获取时区,则也是安全的,因为该方法是线程安全的。

2

没有明确的文件说明TimeZone是线程安全的,因此最安全的做法是假设它不是线程安全的。

TimeZone类有两个实例mutators,与ID和其GMT偏移相关。常识会告诉我们,Calendar.getInstance和SimpleDateFormat没有修改TimeZone对象状态的必要(在第一个情况下,它被用作查找键,在第二个情况下,它被用作格式化上下文)。

常识或确定性-由您选择。


1

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


实际上,TimeZone.getDefault() 和 TimeZone.setDefault() 获取和设置线程本地默认值。看一下源代码! - Stephen C
不是的,https://dev59.com/TXI95IYBdhLWcg3wvgl9 - Tom

0

这看起来是没问题的。但如果你依赖于 TimeZone.getDefault(),那就不一样了。因为另一个线程可能会调用 TimeZone.setDefault()。


实际上,那是安全的。TimeZone.getDefault()TimeZone.setDefault()获取和设置线程本地默认值。请查看源代码! - Stephen C
@StephenC - 不,这不安全。请看https://dev59.com/TXI95IYBdhLWcg3wvgl9 - Tom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接