java - 仅在 Java 1.8.0_45 中出现 ConcurrentModificationException

标签 java concurrency

关于这段代码我有两个问题:

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 already nailed the general reason为什么你得到那个异常(exception)。然而,这似乎是依赖于版本的。我将填写为什么您在 java 8.0_45 中获得它,而不是 1.6.0_45、1.7.0_79、1.8.0_5。

这是因为 Collections.sort() 在 java 8.0_20 中发生了变化。有一篇关于它的深入文章here .在新版本中,按照文章排序,是这样的:

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++;
}

如文章所述:

Contrary to the old Collections.sort, this implementation modifies the modCount of the collection (line 7 above) once the list has been sorted, even if the structure itself didn’t really change (still the same number of elements).

因此即使集合已经排序,它也会进行内部更改,而在此更改之前它不会这样做。这就是为什么你现在得到一个异常(exception)。

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

关于java - 仅在 Java 1.8.0_45 中出现 ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32718852/

相关文章:

java - Jenkins -- 使用 cli 构建作业导致 java.lang.NullPointerException

java - 关于 ConcurrentHashMap javadoc 的说明

java - 位图空指针异常 bitmap = content.getDrawingCache();

java - 如何分析并发 Java 代码

java - 如何使用线程中断方法停止线程

go - 调用runtime.Gosched()与从 channel 接收之间用法上的区别?

java - 数组适配器中出现空指针异常。没有找到 View ?

Java类实例化

c - 如何查询 pthread 以查看它是否仍在运行?

java - 出于可扩展性目的,不使用 ConcurrentHashMap 并发访问 Java Map