我一直在假设Date
和Calendar
都不是线程安全的,但在最近的讨论中,一位同事告诉我Calendar
是线程安全的。
所以,我做了一些研究,并没有提出任何建议。有很多人认为它是线程安全的,很多人认为它不是线程安全的。而且,最重要的是,文档不会以某种方式说出任何内容,不是Calendar
,甚至也不是Date
。
那么,这是什么?
答案 0 :(得分:28)
以下是Java 7中Calendar和GregorianCalendar源代码的链接
如果您阅读代码,您将看到没有任何实例方法同步,并且所有实例字段都不是volatile
。您还将看到即使是字段get
方法也可能导致Calendar实例发生变异。并且由于没有执行同步,因此不同的线程可能会在这样的变异操作之后看到Calendar对象的字段的陈旧版本。
对于记录,字段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没有指定类的线程安全性,那么你应该假设它不是线程安全的。
答案 1 :(得分:4)
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;
}
我认为可以安全地假设该类不线程安全。
答案 2 :(得分:-1)
- 我不确定您的朋友从哪里获取信息,但是用简单直接的语言说话,Calendar class is
不 Thread safe
。
- 我没有在原子语句中找到任何synchronized
个关键字,也没有在Calendar类及其子类中找到volatile
个字段。