java.util.Calendar线程是否安全?

java.util.Calendar线程是否安全?,java,calendar,Java,Calendar,我一直认为Date和Calendar都不是线程安全的,但在最近的一次讨论中,一位同事告诉我Calendar是线程安全的 所以,我做了一些研究,但什么也没发现。有很多人认为它是线程安全的,也有很多人认为它不是线程安全的。而且,最重要的是,文档没有以任何方式说明任何内容,既不针对日历,也不针对日期 那么,它是哪一个呢?来自Oracle的文档没有提到线程安全性: OpenJDK源代码(build b147)以非线程安全的方式实现java.util.Calendar,例如: public void se

我一直认为
Date
Calendar
都不是线程安全的,但在最近的一次讨论中,一位同事告诉我
Calendar
是线程安全的

所以,我做了一些研究,但什么也没发现。有很多人认为它是线程安全的,也有很多人认为它不是线程安全的。而且,最重要的是,文档没有以任何方式说明任何内容,既不针对
日历
,也不针对
日期


那么,它是哪一个呢?

来自Oracle的文档没有提到线程安全性:

OpenJDK源代码(build b147)以非线程安全的方式实现
java.util.Calendar
,例如:

public void setTimeInMillis(long millis) {
  // skipped
  time = millis;
  isTimeSet = true;
  areFieldsSet = false;
  computeFields();
  areAllFieldsSet = areFieldsSet = true;
}

我认为可以安全地假设该类不是线程安全的。

这里是指向Java 7和的源代码的链接

如果阅读代码,您将看到没有一个实例方法是同步的,也没有一个实例字段是易失的。您还将看到,即使是字段
get
方法也会导致日历实例发生变化。而且,由于没有执行同步,不同的线程可能会在这种变异操作之后看到日历对象字段的过时版本

作为记录,get methods字段中的突变操作在调用此方法时发生:

 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
类不是线程安全的,
gregorianalendar
也不是线程安全的,因为它继承了非线程安全的字段和方法

但不要只是相信我的话。自己分析源代码


而且,最重要的是,文档并没有以这样或那样的方式说明任何事情,并没有说明日历,甚至也没有说明日期


如果javadocs没有指定类的线程安全性,那么您应该假设它不是线程安全的。

请参阅that@AlexColeman请注意,第一个答案是“不”,第二个答案是“是”,所有这些讨论都没有任何支持。
Joda Time的+1。如果您关心线程安全问题,那么使用此选项将是一个不错的选择。@DanielC.Sobral然而,第一个选项被提升了8次,得到了正确的答案,并且似乎得到了支持well@mojoken冒着显而易见的风险,线程安全性涉及使用同一实例的多个线程。