8
    package CollectionsTS;

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.List;

    public class ArrayListTS {
        public static void main(String[] args) {
            HashSet<Integer> hset = new HashSet<Integer>();
            for (int i = 0; i <= 1000; i++) {
                hset.add(i);
            }

            MyRunnable mr = new MyRunnable();
            mr.addElements(hset);

            Thread t1 = new Thread(mr,"t1");
            Thread t2 = new Thread(mr,"t2");
            Thread t3 = new Thread(mr,"t3");

            t1.start(); t2.start(); t3.start();

        }
    }

    class MyRunnable implements Runnable {

        List<Integer> ilist = new ArrayList<Integer>();

        public void addElements(HashSet<Integer> hset) {
            ilist.addAll(hset);
        }

        @Override
        public void run() {
            Collections.sort(ilist);
            if (ilist.size() > 0)
                System.out.println( Thread.currentThread().getName() +" = "+ilist.get(ilist.size() - 1));
            else
                System.out.println("List is empty");
        }
    }

Excption thrown is ConcurrentModificationException , I am wondering the code is not modifying the list (not structurally) .

Exception in thread "t1" t3 = 1000
Exception in thread "t2" java.util.ConcurrentModificationException
    at java.util.ArrayList.sort(Unknown Source)
    at java.util.Collections.sort(Unknown Source)
    at CollectionsTS.MyRunnable.run(ArrayListTS.java:37)
    at java.lang.Thread.run(Unknown Source)
java.util.ConcurrentModificationException
    at java.util.ArrayList.sort(Unknown Source)
    at java.util.Collections.sort(Unknown Source)
    at CollectionsTS.MyRunnable.run(ArrayListTS.java:37)
    at java.lang.Thread.run(Unknown Source)

I have method which returns the maximum out of list , I don't want to usr Collections.max() , I want to sort the list in multithreaded env with help of collections.sort method.

Collections.sort method sometimes throws ConcurrentModificationException in multithreaded environment . List is not being modified structurally.

Could anyone help me on this ?

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
Shiva Garg
  • 826
  • 9
  • 17

2 Answers2

12

You have created a single MyRunnable instance, which has an ArrayList as a member variable. Then in 3 separate threads you attempt to sort the ArrayList. Calling sort will structurally modify the list. That is why it results in a ConcurrentModificationException.

Brett Okken
  • 6,210
  • 1
  • 19
  • 25
  • ok , but how come calling a sort method , will structurally modify the list , as the size of list remain same . – Shiva Garg Mar 31 '15 at 03:32
  • 2
    While the documentation is not terribly clear, the sort method is also considered a modification. Basically any method which changes the content of the method EXCEPT set is considered a modification. Here is the jdk8 source for the sort method. You can see the mod count being incremented: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/ArrayList.java?av=f#1443 – Brett Okken Mar 31 '15 at 12:04
  • @ShivaGarg does this answer your question? – Brett Okken Apr 01 '15 at 11:10
2

This is due to fact that Collections.sort() was changed in java 8.0_20. There's an in-depth article about it here. Contrary to the old Collections.sort, this implementation modifies the modCount of the collection once the list has been sorted, even if the structure itself didn’t really change (still the same number of elements).

So it will do an internal change even if the collection is already sorted, whereas before that change it didn't do that. That's why you're getting an exception now.

The actual fix is to not to sort a collection using multiple threads at the same time. You shouldn't do that.