我一直认为Date和Calendar都不是线程安全的,但在最近的一次讨论中,一位同事告诉我Calendar是线程安全的。
因此,我做了一些研究,但一无所获。有很多人认为它是线程安全的,也有很多人认为它不是线程安全的。而且,最重要的是,文档并没有以这样或那样的方式说明任何事情,无论是对Calendar,还是对Date。
那么,到底是哪一个呢?
发布于 2012-08-27 00:20:16
下面是Java7中Calendar和GregorianCalendar源代码的链接
如果阅读代码,您将看到没有一个实例方法是同步的,并且没有一个实例字段是volatile。您还将看到,即使是字段get方法也会导致日历实例发生变化。由于没有执行同步,因此不同的线程可能会看到Calendar对象字段在这样的变异操作之后的过时版本。
对于记录,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类不是线程安全的,GregorianCalendar也不是,因为它继承了非线程安全的字段和方法。
但不要只相信我的话。对源代码进行自己的分析。
,最重要的是,文档没有以这种或那种方式说明任何事情,也没有说明日历,甚至也没有说明日期。
如果javadoc没有指定类的线程安全性,那么您应该认为它不是线程安全的。(特别是如果该类在设计上是可变的。)
发布于 2012-08-27 00:15:29
甲骨文的文档没有提到线程安全: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;
}我认为可以安全地假设这个类是线程安全的,而不是线程安全的。
https://stackoverflow.com/questions/12131324
复制相似问题