【问题标题】:Why we need fail fast and fail safe software design? [closed]为什么我们需要快速失败和故障安全的软件设计? [关闭]
【发布时间】:2017-08-16 12:49:19
【问题描述】:

我们知道 Java 具有快速故障和故障安全的迭代设计。

我想知道,为什么我们基本上需要这些。这种分离有什么根本原因吗? .这种设计有什么好处?

除了集合迭代,Java 在其他任何地方都遵循这种设计?

谢谢

【问题讨论】:

  • “我们知道 Java 具有快速故障和故障安全的迭代设计”——我们知道吗?
  • 快速失败可以最大限度地减少在故障环境中可能造成的损害
  • @JavaUser 如果用户回答了您的问题,请同时接受他的回答 (Accepting Answers: How does it work?)。如果不是,请说明什么仍未得到答复,这是 StackOverflow 的一个非常重要的部分,非常感谢。

标签: java collections iterator fail-fast


【解决方案1】:

对于程序员来说,如果代码包含错误,则尝试尽快失败是很有用的。最好是在编译时,但有时这是不可能的。

因此可以更早地检测到错误。否则,可能会出现一个错误仍未被发现,并且在您的软件中包含多年且没有人注意到该错误。

因此,我们的目标是尽早发现错误和错误。因此,接受参数的方法应该立即检查它们是否在允许的范围内,这将是迈向快速失败的一步。

这些设计目标无处不在,不仅仅是在迭代中,仅仅是因为这是一个好主意。但有时您想在可用性或其他因素之间进行权衡。

例如,Set 实现允许 null 值,这是许多错误的根源。新的 Java 9 集合不允许这样做,并在尝试添加此类时立即抛出异常,这是 fail-fast


您的 迭代器 也是一个很好的例子。我们有一些 fail-fast 迭代器,它们不允许在迭代时修改集合。主要原因是因为它很容易成为错误的来源。因此他们抛出了ConcurrentModificationException

在迭代的特殊情况下,需要有人指定事情应该如何工作。当一个新元素在迭代过程中出现或被删除时,迭代应该如何表现?应该在迭代中包含/删除它还是应该忽略它?

例如,ListIterator 提供了一个非常定义明确 的选项来迭代 List 并对其进行操作。在那里你只能操作迭代器当前所在的对象,这使它定义明确

另一方面,还有一些故障安全迭代方法,例如使用ConcurrentHashMap。它们不会抛出此类异常并允许修改。然而,他们在原始集合的副本上工作,这也解决了“如何”的问题。所以地图上的变化不会反映在迭代器中,迭代器在迭代时完全忽略任何变化。这会增加成本,每次迭代都必须创建一个完整的副本。


就我个人而言,那些 fail-safe 变体不是一种选择。我使用 fail-fast 变体并记住我想要操作的内容。迭代完成后,我执行那些记忆中的操作。

这对程序员来说写起来不太舒服,但你会得到 fail-fast 的优势。这就是我要权衡可用性的意思。

【讨论】:

    猜你喜欢
    • 2013-06-26
    • 2015-12-17
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 2011-05-27
    • 1970-01-01
    • 2011-01-20
    相关资源
    最近更新 更多