java.util.ConcurrentModification…

本文探讨了在Java中使用迭代器遍历列表时遇到的ConcurrentModificationException异常。异常发生在尝试直接通过列表对象移除元素而非迭代器的remove方法时。文章详细解释了异常产生的原因,并提供了解决方案。

错误代码:

public static void main(String[] args) {
  List list = new ArrayList();
  list.add("1");
  list.add("2");
  list.add("3");
  list.add("4");
  Iterator it = list.iterator();
  while (it.hasNext()) {
   if(it.next().equals("1")){
    list.remove("1");
   }
   
  }
 }

抛出异常:

java.util.ConcurrentModificationException
 at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
 at java.util.AbstractList$Itr.next(AbstractList.java:343)
 at com.baihe.util.ZnplUtil.main(ZnplUtil.java:256)

原因:

在内部类Itr中,有一个字段expectedModCount ,初始化

时等于modCount,即当我们调用list.iterator()返回迭代器时,该字段被初始化为等于modCount。在类Itr中next/remove方法都有调用checkForComodification()方法,在该方法中检测modCount == expectedModCount,如果不相当则抛出异常ConcurrentModificationException。
前面说过,在集合的修改操作(add/remove)中,都对modCount操作了。
在看看刚开始提出的那段代码,在迭代过程中,执行list.remove(val),使得modCount+1,当下一次循环时,执行 it.next(),checkForComodification方法发现modCount != expectedModCount,则抛出异常。

解决办法:

如果想要在迭代的过程中,执行删除元素操作怎么办?
再来看看内部类Itr的remove()方法,在删除元素后,有这么一句expectedModCount = modCount,同步修改expectedModCount 的值。所以,如果需要在使用迭代器迭代时,删除元素,可以使用迭代器提供的remove方法。对于add操作,则在整个迭代器迭代过程中是不允许的。 其他集合(Map/Set)使用迭代器迭代也是一样。



### 解决MySQL 'Host is not allowed to connect' 错误以及Spring应用关闭时的ConcurrentModificationException问题 #### 1. MySQL 'Host is not allowed to connect' 错误分析与解决方法 当遇到 `Host 'AAAAA' is not allowed to connect to this MySQL server` 的错误时,这通常是由于MySQL用户的主机权限设置不当引起的。可以通过以下方式解决问题: ##### 修改用户权限 登录到MySQL并更新用户表中的`host`字段以允许远程连接: ```sql UPDATE user SET host = '%' WHERE user = 'root'; -- 将根用户权限扩展至所有主机[^1] FLUSH PRIVILEGES; -- 刷新权限缓存以便更改生效[^1] ``` 如果需要更精细控制而非开放给所有主机,则可以替换 `'%'` 为具体的客户端IP地址。 另外还需确认MySQL服务监听的是正确的网络接口而不是仅仅本地回环(`127.0.0.1`)。编辑配置文件 `/etc/mysql/my.cnf` 或者相应位置找到 `[mysqld]` 部分下的 `bind-address` 设置项改为 `0.0.0.0` 来接受任何来源的TCP/IP 连接请求,并重启服务使改动有效。 最后别忘了检查操作系统层面是否有防火墙阻止了对外部世界的3306端口访问。 --- #### 2. Spring 应用程序关闭期间发生的 ConcurrentModificationException 处理方案 对于在Spring应用程序正常退出过程中抛出的 `ConcurrentModificationException` ,这是因为在迭代集合的同时该集合被修改所引发的一种异常情况。以下是几种常见的处理办法: ##### 方法一:使用同步结构替代原始数据结构 考虑采用线程安全的数据容器比如 CopyOnWriteArrayList 替代普通的 ArrayList 。CopyOnWriteArrayList 是一种读写分离模式实现,在遍历时即使有其他线程对其进行了增删改操作也不会影响当前正在执行的循环流程。 示例代码如下所示: ```java import java.util.concurrent.CopyOnWriteArrayList; List<String> list = new CopyOnWriteArrayList<>(); // 对list的操作... for(String item : list){ System.out.println(item); } ``` ##### 方法二:复制一份副本再进行迭代 先创建原列表的一个快照版本然后再基于这个静态图像做进一步处理能够避免因动态变化带来的干扰。 ```java List<YourType> safeCopy = new ArrayList<>(originalList); Iterator<YourType> iterator = safeCopy.iterator(); while(iterator.hasNext()){ YourType obj = iterator.next(); // Process each object without worrying about modification exceptions. } ``` ##### 方法三:捕获异常并合理应对 虽然这不是最优雅的方式但在某些特殊场景下确实可行——即明确知道哪些地方可能会触发此类问题之后针对性地加入try-catch语句块来捕捉可能出现的并发修改例外状况从而采取相应的补救措施或者忽略它继续往下走。 ```java try { for(Entry entry : map.entrySet()) { ... } } catch (ConcurrentModificationException e) {} ``` 以上三种策略可以根据实际需求灵活选用其中任意一种或组合起来运用达到最佳效果。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jarry.liu

如果对您有帮助,鼓励下博主吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值