当前位置: 首页 > 面试题库 >

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

端木鹏
2023-03-14
问题内容

我一直在假设线程安全Date也不Calendar是线程安全,但是在最近的一次讨论中,一位同事告诉我Calendar线程安全。

因此,我做了一些研究,却一无所获。很多人认为它是线程安全的,很多人认为它不是线程安全的。而且,最重要的是,文档没有以一种或另一种方式说任何话,不是为了Calendar,甚至不是Date

那是什么呢?


问题答案:

这是指向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没有指定类的线程安全,则应 假定 它不是线程安全的。



 类似资料:
  • 我有一个在Oracle 11g DB上运行的insert语句,如下所示: 这里有一个处理PostgreSQL的类似问题。但是,由于Oracle序列由所有会话共享,所以我不能相信DB会给出当前会话中最后插入的值。

  • 问题内容: 我有多个线程试图更新MySQL数据库?使用executeUpdate方法是线程安全的吗? 问题答案: 不,使用它不是线程安全的。 实际上,如果其他某个线程使用一条语句,然后另一个线程调用executeUpdate(),则另一个线程的s(如果有的话)将被关闭。“ javadoc.sql.Statement的JavaDoc(PreparedStatement是其子类型) ”如果存在打开的语

  • 假设我有下面的代码,并且makePool可以被多个线程调用。我正在使用ThreadFactoryBuilder来确保线程具有唯一的名称。

  • 问题内容: 我知道文档说明该对象是线程安全的,但这是否意味着从所有方法对其进行的所有访问都是线程安全的?因此,如果我一次从多个线程中调用它,并且一次在同一实例上调用它,会不会发生什么不好的事情? 问题答案: 快速答案是肯定的,它们是线程安全的。但是不要让它在那里… 首先,一个小的内部管理是一个接口,任何不是线程安全的实现都将破坏书面合同。您包括的链接是指,它具有一定的灵巧性。 您包含的链接引起了一

  • 问题内容: 从Java使用gRPC时,我可以缓存存根(客户端)并在多线程环境中调用它们吗?或者通道是线程安全的并且可以安全地缓存吗? 如果网络中断,我应该重新创建通道还是它足够智能以重新连接?我在http://www.grpc.io/docs/上找不到相关信息 谢谢 问题答案: 回答第一个问题: 通道是线程安全的;标有注释。存根也是线程安全的,这就是为什么重新配置会创建新的存根的原因。 回答第二个

  • 问题内容: 我知道Struts2 Action类是线程安全的,因为这些操作放在了值堆栈中。值堆栈又是动作上下文的一部分。由于操作上下文是线程本地的,因此存储在操作上下文中的值(包括值堆栈)在每个线程中都是唯一的。因此,动作是线程安全的。 但是考虑一下拦截器:它们确实很有用,它们为程序员完成了所有繁琐的小工作……例如验证,获取参数值等。但是要考虑的是:拦截器可以在多个请求之间共享。那么这会使拦截器线