ConcurrentModificationException仅在Java 1.8.0_45中

Alv*_*ins 4 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在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它工作正常.

eis*_*eis 9

@nbokmans已经确定了你获得该例外的一般原因.但是,这似乎与版本有关.我将填写为什么你在java 8.0_45而不是1.6.0_45,1.7.0_79,1.8.0_5中得到它.

这是因为Collections.sort()在java 8.0_20中已更改.这里有一个深入的一篇文章关于它在这里.在新版本中,根据文章,排序是这样的:

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++;
}
Run Code Online (Sandbox Code Playgroud)

就像文章解释的那样:

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

因此即使集合已经排序,它也会进行内部更改,而在更改之前它不会这样做.这就是你现在得到例外的原因.

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