当前位置: 首页 > 面试题库 >

ConcurrentModificationException仅在Java 1.8.0_45中

吴嘉禧
2023-03-14
问题内容

关于此代码,我有两个问题:

import java.util.*;

public class TestClass {

    private static List<String> list;   
    public static void main(String[] argv) {

        list = generateStringList(new Random(), "qwertyuioasdfghjklzxcvbnmPOIUYTREWQLKJHGFDSAMNBVCXZ1232456789", 50, 1000);

//      Collections.sort(list, new Comparator<String>() {
//          public int compare(String f1, String f2) {
//              return -f1.compareTo(f2);
//          }
//      });

        for (int i = 0; i < 500; i++) {
            new MyThread(i).start();
         }

    }

    private static class MyThread extends Thread  {
        int id;
        MyThread(int id) { this.id = id; }
        public void run() {

            Collections.sort(list, new Comparator<String>() {
                public int compare(String f1, String f2) {
                    return -f1.compareTo(f2);
                }
            });

            for (Iterator it = list.iterator(); it.hasNext();) {
                String s = (String) it.next();
                try {
                    Thread.sleep(10 + (int)(Math.random()*100));
                }catch (Exception e) { e.printStackTrace(); }

                System.out.println(id+" -> "+s);
            }           
        }       
    }

    public static List<String> generateStringList(Random rng, String characters, int length, int size)
    {
        List<String> list = new ArrayList<String>();
        for (int j = 0; j < size; j++) {
            char[] text = new char[length];
            for (int i = 0; i < length; i++)
            {
                text[i] = characters.charAt(rng.nextInt(characters.length()));
            }
            list.add(new String(text));
        }
        return list;
    }
}

我在java 1.8.0_45上运行此代码java.util.ConcurrentModificationException

1)如果我在thread.start之前分解排序,为什么也会出现异常?

2)为什么我只在Java 1.8.0_45上得到了例外?在1.6.0_45、1.7.0_79和1.8.0_5上可以正常工作。


问题答案:

@nbokmans已经确定了导致该异常的一般原因。但是,这确实取决于版本。我将填写为什么在Java
8.0_45中而不是1.6.0_45、1.7.0_79、1.8.0_5中得到它。

这是由于在Java
8.0_20中Collections.sort()被更改的事实。有一个关于它的深入文章在这里。在新版本中,根据文章,排序如下:

public void sort(Comparator<? super E> c) {
  final int expectedModCount = modCount;
  Arrays.sort((E[]) elementData, 0, size, c);
  if (modCount != expectedModCount) {
    throw new ConcurrentModificationException();
  }
  modCount++;
}

如文章所述:

与旧的Collections.sort相反,此实现在对列表进行排序后修改了集合的modCount(上面的第7行),即使结构本身并没有真正改变(元素数量仍然相同)。

因此,即使对集合进行了排序,它也将进行内部更改,而在更改之前,它没有这样做。这就是为什么您现在要例外。

实际的解决方法是不要同时使用多个线程对集合进行排序。你不应该那样做。



 类似资料:
  • 问题内容: 我正在尝试按时间范围的开始时间排序列表(用开始时间和结束时间表示为Time []数组)。我正在尝试使用以下嵌套循环来做到这一点: 但它在行上抛出了一个(顶部的那个)。我以前从未见过这种例外情况,有人可以向我解释它的含义和原因。 我也愿意为此提出更好的算法建议。 问题答案: workingList.remove(compareTo); 您在迭代时正在修改集合。 您应该使用类似: 也有一些

  • 问题内容: 那是我收到的错误。 我的方法看起来像 所以我的理解是,这意味着我要在迭代器完成之前更改其大小,这就是您得到的错误。这是正确的,因为reactStateChange之一是用于将对象从hashMap中移除。如何安全地执行此操作,以便在删除某些内容时可以让Iterator提前知道,从而可以避免此错误。提前致谢。如果需要更多详细信息,我们将很高兴满足您的要求。 问题答案: 从基础集合中删除元素

  • 问题陈述:为以下场景设计系统: 1.物料列表包含多个物料的物料编码、名称、费率和数量。 每当在列表中添加新项目时,都要检查项目编码的唯一性。用新产品的价格注册一个新产品。 项目的时间比率可能会更改。 每当发出或接收一个项目时,检查该项目的存在性并更新数量。 出库时,还要检查数量的可用性。 用户可能还想知道一个项目的价格/数量。 查找多少项目的成本超过给定金额。金额将是一个参数。 请记住,如果给出了

  • 问题内容: 我有一个方法test(),其中我试图将两个LinkedHashMap相互比较,并通过删除键/值对(如果在两个LHM中都找到)来修改其中一个映射的内容。运行此方法时,我不断收到ConcurrentModificationException。我知道为什么会收到异常(因为我正在尝试修改正在循环的列表)。我不确定如何进行此操作。到目前为止,我有以下代码: 问题答案: 您可以使用迭代器:

  • 问题内容: 我正在使用以下代码测试集合: 我不明白为什么删除“ b”可以,但是其他NG? 问题答案: 首先要知道的是(如JLS所述)以下增强的for循环: 等效于: 如果查看中的迭代器的实现,您将看到: 不检查并发修改,仅使用大小检查我们是否在列表的末尾: 首先要做的是调用以查看在迭代过程中列表是否被修改: 因此,当您迭代并删除列表的倒数第二个元素时,下一条指令将是对的调用,该调用将返回,因为删除

  • 问题内容: 为什么下面的代码抛出ConcurrentModificationException?JoshBloch可以避免ConcurrentModificationException。 问题答案: 使用“ for each”循环时,不能在列表上使用remove。相反,您可以使用此方法在迭代器上调用remove: 如果您实际上想用“ 200”代替每个值,或用其他值代替,则建立一个新列表可能更有意义