【问题标题】:Why is Java's SimpleDateFormat class non thread safe?为什么 Java 的 SimpleDateFormat 类是非线程安全的?
【发布时间】:2012-09-19 14:30:05
【问题描述】:

问题与 Java 的 SimpleDateFormat 类有关。我在文档中读到了

日期格式不同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问一个格式,必须在外部同步。

显然,我在被它以最隐晦的方式击中后读过。

有谁知道为什么需要通过“格式”方法访问类成员中的状态信息?

这是某种速度优化吗?我找不到正当理由。

【问题讨论】:

  • 这只是它的定义。这种情况已经有一段时间了。也许更好的问题是他们为什么不修复它?
  • 这可能只是一个设计选择。我最近一直在使用这样的代码,它将临时状态存储在成员变量中,并且很难调试/重构。我不会推荐它,我什至会说这不是很好的做法。
  • 也许它使用了一种享元模式以节省一些内存。
  • 委婉地说@Brian 是不好的做法。这是一种糟糕的做法。
  • 这只是ooooooooooooooooooold。我们往往会忘记 Java 1 是在 20 多年前起草的除了 SGI 的破解团队之外,没有人试图开发“真正的”软件。

标签: java api date concurrency thread-safety


【解决方案1】:

你的答案几乎就在这里:

/* * (C) 版权所有 Taligent, Inc. 1996 - 保留所有权利

在 1.4 热点之前,用 Java 编写多线程代码主要是研究生的家庭作业。在 Web 应用服务器和容器驱动的高并发系统兴起之前,该语言已经出现了大约 10 年,而我们大多数人(无论如何都不是 Android)大部分时间都在使用该系统。

在 1996 年,垃圾收集是一个非常缓慢和痛苦的过程,通常会让你的 UI 暂停并在它发生时看起来被锁定,就像明智地创建新对象被认为非常昂贵(当你与 Windows 战斗时创建连续的内存空间) 95 共享 4MB 物理内存而没有 L2 CPU 缓存需要一些时间.....)。

因此,在多线程极为罕见且内存非常宝贵的环境中(您的普通用户可能仍在使用 486 或 Pentium 1,系统内存为 8MB 甚至 4MB....)尽可能地重用单个 Calendar 实例是有意义的,Calendar 本身就是一个笨重的野兽。

今天我们可以嘲笑像这样的有状态的类是多么可怕的做法,但在当时它也很容易被辩护为正确的选择。

捍卫 Sun 对 100% 向后兼容性的痴迷并且永不更新是另一回事!

【讨论】:

  • 日期格式化是如此复杂和昂贵,1 个对象的开销应该可以忽略不计。真正的限制可能来自 Calendar API,这使得设计线程安全且快速的格式化程序成为不可能。 Calendar API 显然设计得很糟糕,而且广受憎恨。
  • 这是比较 CPU 时间和内存使用情况。当内存受到限制时,浪费的内存就是浪费的内存。在非流水线/原始流水线处理器上,您可以在处理内存总线所需的时间内进行大量计算。此外,GC 暂停中浪费的内存的性能成本是在一个不可预测的时间,而不是对特定用户操作的较慢响应。我没有数据,也无法生成任何数据,但如果在普通的 1996 jvm+台式计算机上,日历对象分配+gc 实际上与计算成本相当。
  • 计算需要大量的内存读取/写入,大量的方法调用。原始 VM 也无法优化它们。你给了作者太多怀疑的好处;这很可能只是 API 设计失败。
  • 我怀疑缺乏线程安全的根本原因是 Java 没有机制可以让被调用函数返回多个值,而无需创建新的堆对象来保存它们或滥用现有对象那个目的。
【解决方案2】:

看起来它是出于性能原因而完成的。我没有看到其他解释。

这里有一个很好的总结: Why is Java's SimpleDateFormat not thread-safe?

【讨论】:

  • 它可以是线程安全且快速的。性能原因必须植根于某些工程甚至政治原因。
猜你喜欢
  • 2011-10-14
  • 1970-01-01
  • 2010-12-10
  • 1970-01-01
  • 2015-07-24
  • 1970-01-01
相关资源
最近更新 更多