失败的原子调用应该使得对象保持在被调用之前的状态,所谓:失败原子性
- 几种途径实现:
- 设计一个不可变对象,其失败原子性是显然的
- 对于可变参数,执行前检查参数有效性
- 避免执行一半报错,后续无法执行导致状态不一致
- 调整计算顺序,使得任何可能失败的部分,放到状态修改前,进而获得原子性
- (不常用)编写恢复代码,拦截操作中的失败,使对象回滚到原来的状态
- 主要用于永久性的数据结构
- 在对象的临时拷贝上做操作,成功后再用临时拷贝的结果代替对象的内容
- 如果失败,不影响原有对象的状态
- 由于是临时数据,计算过程更加迅速
- Collections.sort 先将输入列表转到数组中,降低排序内循环访问元素的开销
- 如上代码,如果不做检查size == 0 ,仍然会抛出异常,
- 但是size 域处于,下标为-1的不一致状态,其他操作都无法进行
- 别的方法使用时,会抛出与之不匹配的异常
并非都能做到失败原子性:
- 比如俩线程同时操作一个对象,就可能会导致不一致状态:ConcurrentModificationException
- 错误(相对于异常)通常是不可恢复的,没必要保持失败一致性
一般,方法规范的一部分,任何异常都应该使得对象保持在方法调用之前的状态
- 如果违反该规范,对象将会处于什么状态
- 大部分api 没有做到这一点