java.util.Calendar线程是否安全?
我一直在假设两者都不是线程安全的,但是,在最近的一次讨论中,一位同事告诉我线程安全。Date
Calendar
Calendar
所以,我做了一些研究,什么也没想出来。有很多人认为它是线程安全的,很多人认为它不是线程安全的。而且,最重要的是,文档没有以这种或那种方式说明任何内容,不是针对 ,甚至不是针对 。Calendar
Date
那么,它是什么呢?
我一直在假设两者都不是线程安全的,但是,在最近的一次讨论中,一位同事告诉我线程安全。Date
Calendar
Calendar
所以,我做了一些研究,什么也没想出来。有很多人认为它是线程安全的,很多人认为它不是线程安全的。而且,最重要的是,文档没有以这种或那种方式说明任何内容,不是针对 ,甚至不是针对 。Calendar
Date
那么,它是什么呢?
以下是Java 7中Calendar和GregorianCalendar源代码的链接
如果阅读代码,您将看到没有同步任何实例方法,也没有实例字段是 。您还将看到,即使字段方法也可能导致 Calendar 实例发生突变。由于没有执行同步,因此在进行此类更改操作后,不同的线程可能会看到 Calendar 对象字段的过时版本。volatile
get
为了记录,现场 get 方法中的突变操作发生在 /期间调用此方法:
1555 protected void complete()
1556 {
1557 if (!isTimeSet)
1558 updateTime();
1559 if (!areFieldsSet || !areAllFieldsSet) {
1560 computeFields(); // fills in unset fields
1561 areAllFieldsSet = areFieldsSet = true;
1562 }
1563 }
简而言之,该类不是线程安全的,也不是,因为它继承了非线程安全的字段和方法。Calendar
GregorianCalendar
但不要只听我说。对源代码进行自己的分析。
而且,最重要的是,文档没有以某种方式说明任何内容,不适用于日历,甚至不适用于日期。
如果 javadocs 没有指定类的线程安全,那么你应该假定它不是线程安全的。(特别是如果类在设计上是可变的。
来自Oracle的文档没有提到线程安全:http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html。
OpenJDK 源代码(build b147)以非线程安全的方式实现,例如:java.util.Calendar
public void setTimeInMillis(long millis) {
// skipped
time = millis;
isTimeSet = true;
areFieldsSet = false;
computeFields();
areAllFieldsSet = areFieldsSet = true;
}
我认为可以安全地假设该类不是线程安全的。