Wednesday 26 August 2015

Fail fast Iterator

Fail fast iterator while iterating through the collection, instantly throws java.util.ConcurrentModificationException if there is structural modification  of the collection.

Thus, in the case of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Reasons:

In Single Threaded Environment

After the creation of the iterator, structure is modified at any time by any method other than iterator's own remove method.

Case#1:
The Collection is internally modified, while a thread is iterating over it.
import java.util.HashMap;
import java.util.Map;

public class InternalModifyExc {

      public static void main(String[] args) {
            Map<String, Integer> map = new HashMap<String, Integer>();

            map.put("Key1", 1);
            map.put("Key2", 2);
            map.put("Key3", 3);

            /* Remove a value of the map, while iterating over it.
             * The following code throws ConcurrentModificationException.
             * */
            for(String key: map.keySet()) {
                  if(map.get(key) == 1)
                        map.remove(key);
            }
            System.out.println("No Exception found!");
      }
}
Output:
Exception in thread "main" java.util.ConcurrentModificationException
     at java.util.HashMap$HashIterator.nextEntry(HashMap.java:926)
     at java.util.HashMap$KeyIterator.next(HashMap.java:960)
     at main.java.Example.main(Example.java:18)

Case#2:
After the creation of an iterator, the Collection is internally modified by any method other than the iterator’s own methods for removal and addition.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IterOwnMethod {

      public static void main(String[] args) {
            List<String> list = new ArrayList<String>();


            list.add("Rahul");
            list.add("Mehul");
            list.add("Manisha");

            // Get an iterator.
            Iterator<String> ite = list.iterator();

            /**
             * Remove the first object of the list.
             * This statement will force the iterator
             * to throw a ConcurrentModificationException.
             * */
            list.remove(0);

            while(ite.hasNext()) {
                  System.out.println(ite.next());
            }
      }
}
Output:
Exception in thread "main" java.util.ConcurrentModificationException
     at java.util.HashMap$HashIterator.nextEntry(HashMap.java:926)
     at java.util.HashMap$KeyIterator.next(HashMap.java:960)
     at main.java.Example.main(Example.java:18)

Multiple Threaded Environment
If one thread is modifying the structure of the collection while other thread is iterating over it.

Case#3:
Two iterators simultaneously modify the internal structure of a Collection.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class MultiThread {

      public static void main(String[] args) {
            List<String> list = new ArrayList<String>();
            // Insert some sample values.
            list.add("Rahul");
            list.add("Manisha");
            list.add("Mehul");

            // Create two iterators.
            Iterator<String> iterator1 = list.iterator();
            Iterator<String> iterator2 = list.iterator();

            /**
             * Remove the first element.
             */
            iterator1.next();
            iterator1.remove();

            /**
             * The second iterator tries to remove the first object.
             * The object does not exist and thus,
             * ConcurrentModificationException is thrown.
             **/
            iterator2.next();
            iterator2.remove();
      }
}
Output:
Exception in thread "main" java.util.ConcurrentModificationException
     at java.util.HashMap$HashIterator.nextEntry(HashMap.java:926)
     at java.util.HashMap$KeyIterator.next(HashMap.java:960)
     at main.java.Example.main(Example.java:18)

Note:
The fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis.

Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

How  Fail  Fast Iterator  come to know that the internal structure is modified:

Iterator read internal data structure (object array) directly. The internal data structure(i.e. object array) should not be modified while iterating through the collection.

To ensure this it maintains an internal  flag "mods". Iterator checks the "mods" flag whenever it gets the next value (using hasNext() method and next() method).

Value of mods flag changes whenever there is an structural modification. Thus indicating iterator to throw ConcurrentModificationException.

No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...