快速失败and安全失败
快速失败:
举个栗子:
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<>();
list.add("包龙星");
list.add("常威");
list.add("来福");
list.add("豹子头");
list.add(null);
Iterator<String> iterator=list.iterator();
while (iterator.hasNext()){
String s=iterator.next();
if(s.equals("常威"));
list.remove("常威");
}
}
运行结果:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at com.Collection.ArrayListTest.main(ArrayListTest.java:23)
jdk上异常解释:某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不确定的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常。执行该操作的迭代器称为快速失败 迭代器,因为迭代器很快就完全失败,而不会冒着在将来某个时间任意发生不确定行为的风险。
也就是说当我们通过迭代器遍历集合时,如果直接通过集合增删了集合中的元素,就会抛出ConcurrentModificationException,称为快速失败!
源码分析:(注意重点红色标记)
Iterator部分源码:
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount; Itr() {} public boolean hasNext() {
return cursor != size;
} @SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
checkForComdification方法
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
Arraylist的删除源码:
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
原理分析:迭代器第一次被调用时,会将一个modCount的值保存在expectedmodCount中,每当迭代器.next()操作遍历下一个元素之时,都会检查modCount变量是否为expectedmodCount值,集合在被遍历期间如果直接通过集合的方法改变集合内容,modCount++,进而导致下次进入.next()方法时匹配失败,抛出异常
ps:java.util包下面的所有的集合类都是快速失败的
安全失败:
采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。
原理:由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发Concurrent Modification Exception。
缺点:基于拷贝内容的优点是避免了Concurrent Modification Exception,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。
java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。
快速失败and安全失败的更多相关文章
- Java笔记-快速失败and安全失败
参考资料:http://blog.csdn.net/chenssy/article/details/38151189 快速失败 fail-fast 安全失败 fail-safe java.util包下 ...
- 【1】ConcurrentModificationException 异常解析和快速失败,安全失败
目录 一.引起异常的代码 二.foreach原理 三.从ArrayList源码找原因 四.单线程解决方案 五.在多线程环境下的解决方法 一.引起异常的代码 以下三种的遍历集合对象时候,执行集合的rem ...
- 170118、快速失败Vs安全失败(Java迭代器附示例)
简介: 当错误发生时,如果系统立即关闭,即是快速失败,系统不会继续运行.运行中发生错误,它会立即停止操作,错误也会立即暴露.而安全失败系统在错误发生时不会停止运行.它们隐蔽错误,继续运行,而不会暴露错 ...
- Java 快速失败( fail-fast ) 安全失败( fail-safe )
原文:http://www.cnblogs.com/ygj0930/p/6543350.html 快速失败( fail-fast ):当你在迭代一个集合的时候,如果有另一个线程正在修改你正在访问的那个 ...
- mysql批量插入语句执行失败的话,是部分失败还是全部失败
项目开发中,正好遇到这个问题. 将一批从外部第三方接口获取到的数据存储到本地mysql数据库,假设接口返回的数据类型为A,经过A到B的转换规则转换后, 要插入数据库的数据类型为B.那么在A获取到100 ...
- Win7 Nginx启动失败 cmd命令失败
Win7 Nginx启动失败 cmd命令失败 Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服 ...
- Java的快速失败和安全失败
文章转自https://www.cnblogs.com/ygj0930/p/6543350.html 一:快速失败(fail—fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进 ...
- 快速解决Kali 更新失败问题
Kali Linux 2018.4 初学者在安装完kali 系统后第一件事往往就是更新软件,但在更新过程中通常会出现各种各样的问题,比如更新提示不含有 'maincontrib' 组件,跳过配置文件 ...
- 犀利点评:csdn某文<第一次创业还是失败了---分享失败的经验>
今天上午在csdn看了一篇创业文,突然想无节操的做一下点评. 原文详细地址如下:http://blog.csdn.net/android_tutor/article/details/9815801 以 ...
随机推荐
- Ti 949 配置 948 i2c
如果不想用 远端 slave,只访问948 选 i2c pass through all =1 :i2c pass through =0/1 0x0c 0x17 0x9e 如果想用远端 sla ...
- taro-安装及使用-npm
taro-安装及使用 https://nervjs.github.io/taro/docs/GETTING-STARTED.html 安装 Taro 项目基于 node,请确保已具备较新的 node ...
- 启动AutoCAD时自动加载.NET开发的DLL
程序组织,建立名为*.bundle的文件夹,创建Contents子文件夹,并将dll,ico等文件放进Contents中,在*.bundle中创建PackageContents.xml文件,内容如下: ...
- rstrip
====== rstrip ====== Description Returns a copy of the string with trailing characters removed. Synt ...
- 深入理解Magento-第九章-修改、扩展、重写Magento代码
(博主提示:本章应该不是原作者的第九章,仅作补充和参考) 作为一个开发者的你,肯定要修改Magento代码去适应你的业务需求,但是在很多时候我们不希望修改Magento的核心代码,这里有很多原因,例如 ...
- 2019 ACM/ICPC Asia Regional shanxia D Miku and Generals (二分图黑白染色+01背包)
Miku is matchless in the world!” As everyone knows, Nakano Miku is interested in Japanese generals, ...
- MAC OpenGL 环境搭建
MAC OpenGL 环境搭建 基础库介绍 先要安装两个库一个是GLEW(OpenGL Extension Wrangler Library),另外一个是GLFW(Graphics Library F ...
- Python中使用item()方法遍历字典的例子
Python中使用item()方法遍历字典的例子 这篇文章主要介绍了Python中使用item()方法遍历字典的例子,for...in这种是Python中最常用的遍历字典的方法了,需要的朋友可以参考下 ...
- Delphi多线程详解
(整理自网络) Delphi多线程处理 1-1多线程的基本概念 WIN 98/NT/2000/XP 是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU 运行时间和资源,或者 ...
- 【android】获取本机ip地址
方法是利用网址:http://pv.sohu.com/cityjson?ie=utf-8,返回String类型的ip地址: public static String getNetIp() { Stri ...