Showing posts with label Java concurrent collections. Show all posts
Showing posts with label Java concurrent collections. Show all posts

Saturday, June 1, 2024

ConcurrentHashMap in Java With Examples

ConcurrentHashMap in Java is introduced as another thread-safe alternative to Hashtable (or explicitly synchronizing the map using synchronizedMap method) from Java 5. ConcurrentHashMap class extends AbstractMap class and implements ConcurrentMap interface through which it provides thread safety and atomicity guarantees.

Why another Map

First thing that comes to mind is why another map when we already have a HashMap or HashTable. If you need to use a Map like structure with in a multi-threaded environment with thread safety you can use a Hashtable or a synchronized HashMap by using Collections.synchronizedMap() method. Then what unique does ConcurrentHashMap in Java offer?

Problem with Hashtable or synchronized Map is that all of its methods are synchronized on a common lock thus only a single thread can access it at any given time, even for read operations, making these data structures slower. ConcurrentHashMap is designed to provide better performance while providing thread safety too.


How performance is improved in ConcurrentHashMap

ConcurrentHashMap in Java is also a hash based map like HashMap, how it differs is the locking strategy used by it. Unlike HashTable (or synchronized HashMap) it doesn't synchronize every method on a common lock. ConcurrentHashMap uses separate lock for separate buckets thus locking only a portion of the Map.

If you have idea about the internal implementation of the HashMap you must be knowing that by default there are 16 buckets. Same concept is used in ConcurrentHashMap and by default there are 16 buckets and also separate locks for separate buckets. So the default concurrency level is 16.

Since there are 16 buckets having separate locks of their own which effectively means at any given time 16 threads can operate on the map concurrently, provided all these threads are operating on separate buckets. So you see how ConcurrentHashMap provides better performance by locking only the portion of the map rather than blocking the whole map resulting in greater shared access.

For locking any of the bucket independently of the other buckets the first node in the bucket is locked by using synchronized keyword. Note that before Java 8, implementation of Java ConcurrentHashMap used to have Segment array with with each segment having its own lock which has been changed from Java 8. Now the first node in the bucket itself is locked using the node's own builtin synchronized monitors.

ConcurrentHashMap Internal implementation in Java
ConcurrentHashMap implementation in Java

Further performance improvement

Performance of Java ConcurrentHashMap is further improved by providing read access concurrently without any blocking. Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove). Retrievals reflect the results of the most recently completed update operations which may mean that retrieval operations may not fetch the current/in-progress value (Which is one drawback). Memory visibility for the read operations is ensured by volatile reads. You can see in the ConcurrentHashMap code that the val and next fields of Node are volatile.

Also for aggregate operations such as putAll and clear which works on the whole map, concurrent retrievals may reflect insertion or removal of only some entries (another drawback of separate locking). Because read operations are not blocking but some of the writes (which are on the same bucket) may still be blocking.

Constructors in Java ConcurrentHashMap

There are five constructors in the ConcurrentHashMap class-

  • ConcurrentHashMap()- Creates a new, empty map with the default initial table size (16).
  • ConcurrentHashMap(int initialCapacity)- Creates a new, empty map with an initial table size accommodating the specified number of elements without the need to dynamically resize.
  • ConcurrentHashMap(int initialCapacity, float loadFactor)- Creates a new, empty map with an initial table size based on the given number of elements (initialCapacity) and initial table density (loadFactor).
  • ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel)- Creates a new, empty map with an initial table size based on the given number of elements (initialCapacity), table density (loadFactor), and number of concurrently updating threads (concurrencyLevel).
  • ConcurrentHashMap​(Map<? extends K,? extends V> m)- Creates a new map with the same mappings as the given map.

Java ConcurrentHashMap example

At this juncture let's see a simple example where a ConcurrentHashMap is created and (key, value) pairs are added to it. Then getting the collection view of the Map it is iterated to display the stored keys and values.

public class CHMDemo {
  public static void main(String[] args) {
    // Creating ConcurrentHashMap
    Map<String, String> cityTemperatureMap = new ConcurrentHashMap<String, String>();
    
    // Storing elements
    cityTemperatureMap.put("Delhi", "24");
    cityTemperatureMap.put("Mumbai", "32");
    //cityTemperatureMap.put(null, "26");
    cityTemperatureMap.put("Chennai", "35");
    cityTemperatureMap.put("Bangalore", "22" );
    
    for (Map.Entry<String, String> e : cityTemperatureMap.entrySet()) {
      System.out.println(e.getKey() + " = " + e.getValue());
    }
  }
}

Null is not allowed in ConcurrentHashMap

Though HashMap allows one null as key but ConcurrentHashMap doesn't allow null as key. In the previous example you can uncomment the line which has null key. While trying to execute the program it will throw null pointer exception.

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class CHMDemo {
  public static void main(String[] args) {
    // Creating ConcurrentHashMap
    Map cityTemperatureMap = new ConcurrentHashMap();
    
    // Storing elements
    cityTemperatureMap.put("Delhi", "24");
    cityTemperatureMap.put("Mumbai", "32");
    // Adding null key
    cityTemperatureMap.put(null, "26");
    cityTemperatureMap.put("Chennai", "35");
    cityTemperatureMap.put("Bangalore", "22" );
    
    for (Map.Entry e : cityTemperatureMap.entrySet()) {
      System.out.println(e.getKey() + " = " + e.getValue());
    }
  }
}
Exception in thread "main" java.lang.NullPointerException
 at java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1011)
 at java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:1006)
 at org.netjs.prog.CHMDemo.main(CHMDemo.java:16)

Atomic operations in ConcurrentHashMap

ConcurrentHashMap in Java provides a lot of atomic methods, let's see it with an example how these atomic methods help. Note that from Java 8 many new atomic methods are added.

Suppose you have a word Map that counts the frequency of every word where key is the word and count is the value, in a multi-threaded environment, even if ConcurrentHashMap is used, there may be a problem as described in the code snippet.

public class CHMAtomicDemo {
  public static void main(String[] args) {
    ConcurrentHashMap<String, Integer> wordMap = new ConcurrentHashMap<>();
    ..
    ..
    // Suppose one thread is interrupted after this line and 
    // another thread starts execution
    Integer prevValue = wordMap.get(word); 
    
    Integer newValue = (prevValue == null ? 1 : prevValue + 1);
    // Here the value may not be correct after the execution of 
    // both threads
    wordMap.put(word, newValue);  
  }
}

To avoid these kind of problems you can use atomic method, one of the atomic method is compute which can be used here.

wordMap.compute(word, (k,v)-> v == null ? 1 : v + 1);

If you see the general structure of the Compute method

compute(K key, BiFunction<? super K,? super V,? extendsV> remappingFunction)
Here BiFunction functional interface is used which can be implemented as a lambda expression.

So here rather than having these lines-

Integer prevValue = wordMap.get(word); 
Integer newValue = (prevValue == null ? 1 : prevValue + 1);
wordMap.put(word, newValue);
you can have only this line
wordMap.compute(word, (k,v)-> v == null ? 1 : v + 1);

The entire method invocation is performed atomically. Some attempted update operations on this map by other threads may be blocked while computation is in progress.

There are several other atomic operations like computeIfAbsent, computeIfPresent, merge, putIfAbsent.

Fail-safe iterator in ConcurrentHashMap

Iterator returned by the Java ConcurrentHashMap is fail-safe which means it will not throw ConcurrentModificationException. It can be seen in the example code where a new (key, value) pair is added while the map is iterated, still it doesn't throw ConcurrentModificationException.

public class CHMDemo {
  public static void main(String[] args) {
    // Creating ConcurrentHashMap
    Map<String, String> cityTemperatureMap = new ConcurrentHashMap<String, String>();
    
    // Storing elements
    cityTemperatureMap.put("Delhi", "24");
    cityTemperatureMap.put("Mumbai", "32");
    cityTemperatureMap.put("Chennai", "35");
    cityTemperatureMap.put("Bangalore", "22" );
    
    Iterator<String> iterator = cityTemperatureMap.keySet().iterator();   
    while (iterator.hasNext()){
      System.out.println(cityTemperatureMap.get(iterator.next()));
      // adding new value, it won't throw error
      cityTemperatureMap.put("Kolkata", "34");        
    }
  }
}

Output

24
35
34
32
22

According to the JavaDocs- The view's iterator is a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

When is ConcurrentHashMap a better choice

ConcurrentHashMap is a better choice when there are more reads than writes. As mentioned above retrieval operations are non-blocking so many concurrent threads can read without any performance problem. If there are more writes and that too many threads operating on the same segment then the threads will block which will deteriorate the performance.

Points to note

  • ConcurrentHashMap in Java is also a hash based map like HashMap, but ConcurrentHashMap is thread safe.
  • In ConcurrentHashMap thread safety is ensured by having separate locks for separate buckets, resulting in better performance.
  • In ConcurrentHashMap class, by default the bucket size is 16 and the concurrency level is also 16.
  • Null keys are not allowed in Java ConcurrentHashMap.
  • Iterator provided by the ConcurrentHashMap is fail-safe, which means it will not throw ConcurrentModificationException.
  • Retrieval operations (like get) don't block so may overlap with update operations (including put and remove).

That's all for this topic ConcurrentHashMap in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference Between HashMap And ConcurrentHashMap in Java
  2. CopyOnWriteArrayList in Java With Examples
  3. How HashMap Works Internally in Java
  4. Java CountDownLatch With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. How to Iterate a HashMap of ArrayLists of String in Java
  2. How to Sort HashSet in Java
  3. Difference Between Comparable and Comparator in Java
  4. Try-With-Resources in Java With Examples
  5. static reference to the non-static method or field error
  6. Race Condition in Java Multi-Threading
  7. Angular Reactive Form Validation Example
  8. Spring MVC Radiobutton And Radiobuttons Form Tag Example

Sunday, March 24, 2024

ConcurrentSkipListMap in Java With Examples

ConcurrentSkipListMap in Java is a scalable concurrent map which implements ConcurrentNavigableMap interface. Though concurrent collections like ConcurrentHashMap and CopyOnWriteArrayList were added in Java 1.5, ConcurrentSkipListMap and the similar set implementation ConcurrentSkipListSet were added in Java 1.6.


ConcurrentNavigableMap interface

ConcurrentNavigableMap interface in Java is a ConcurrentMap supporting NavigableMap operations, and recursively so for its navigable sub-maps. It was added in Java 1.6.

ConcurrentNavigableMap interface in turn extends NavigableMap interface. Where NavigableMap is a SortedMap extended with navigation methods returning the closest matches for given search targets. Methods lowerEntry, floorEntry, ceilingEntry, and higherEntry return Map.Entry objects associated with keys respectively less than, less than or equal, greater than or equal, and greater than a given key, returning null if there is no such key. Similarly, methods lowerKey, floorKey, ceilingKey, and higherKey return only the associated keys. All of these methods are designed for locating, not traversing entries.

ConcurrentSkipListMap in Java

Since ConcurrentSkipListMap implements ConcurrentNavigableMap, it is a sorted map just like TreeMap in Java (Which also implements NavigableMap interface), with added functionality of being concurrent.

ConcurrentSkipListMap is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used.

Java ConcurrentSkipListMap constructors

ConcurrentSkipListMap class provides four constructors, which are as follows-

  • ConcurrentSkipListMap()- Constructs a new, empty map, sorted according to the natural ordering of the keys.
  • ConcurrentSkipListMap(Comparator<? super K> comparator)- Constructs a new, empty map, sorted according to the specified comparator.
  • ConcurrentSkipListMap​(Map<? extends K,? extends V> m)- Constructs a new map containing the same mappings as the given map, sorted according to the natural ordering of the keys.
  • ConcurrentSkipListMap​(SortedMap<K,? extends V> m)- Constructs a new map containing the same mappings and using the same ordering as the specified sorted map.

ConcurrentSkipListMap class in Java implements a concurrent variant of SkipLists data structure providing expected average log(n) time cost for the containsKey, get, put and remove operations and their variants. Insertion, removal, update, and access operations safely execute concurrently by multiple threads.

All Map.Entry pairs returned by methods in ConcurrentSkipListMap class and its views represent snapshots of mappings at the time they were produced.

No nulls in ConcurrentSkipListMap

Note that ConcurrentSkipListMap class in Java does not permit the use of null keys or values because some null return values cannot be reliably distinguished from the absence of elements.

Java example creating ConcurrentSkipListMap

Let's see an example where we add some values in a ConcurrentSkipListMap and in the output it can be seen that it is sorted based on the natural ordering of its keys. In this example keys are Strings and for String natural ordering is ascending alphabetical order. So when you loop the map you'll see it is sorted based on the keys.

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;

public class CSMDemo {
  public static void main(String[] args) {
    ConcurrentNavigableMap<String, String> cityMap = new ConcurrentSkipListMap<String, String>();
    cityMap.put("ND", "New Delhi");
    cityMap.put("MU", "Mumbai");
    cityMap.put("CH", "Chennai");
    cityMap.put("HD", "Hyderabad");
    Set<Map.Entry<String, String>> citySet = cityMap.entrySet();
    citySet.forEach((m)->System.out.println("key " + m.getKey() 
              + " value " + m.getValue()));
  }
}

Output

key CH value Chennai
key HD value Hyderabad
key MU value Mumbai
key ND value New Delhi

Here it can be seen that ConcurrentNavigableMap is sorted on the keys.

ConcurrentSkipListMap with Comparator

If you want sorting to be done in reverse order then you can pass a Comparator as a parameter when constructing a ConcurrentSkipListMap.

public class CSMDemo {
  public static void main(String[] args) {
    // With Comparator
    ConcurrentNavigableMap<String, String> cityMap = new ConcurrentSkipListMap<String, String>((String s1, String s2) -> s1.compareTo(s2));
    cityMap.put("ND", "New Delhi");
    cityMap.put("MU", "Mumbai");
    cityMap.put("CH", "Chennai");
    cityMap.put("HD", "Hyderabad");
    Set<Map.Entry<String, String>> citySet = cityMap.entrySet();
    citySet.forEach((m)->System.out.println("key " + m.getKey() 
             + " value " + m.getValue()));
  }
}

Output

key CH value Chennai
key HD value Hyderabad
key MU value Mumbai
key ND value New Delhi

Here it can be seen that elements in the ConcurrentNavigableMap are now sorted in reversed order.

Navigational methods in Java ConcurrentSkipListMap

As already mentioned ConcurrentSkipListMap in Java implements ConcurrentNavigableMap interface so it has many navigation methods returning the closest matches for given search targets. Let's see some of them in example code.

  • descendingKeySet()- Returns a reverse order NavigableSet view of the keys contained in this map.
  • floorEntry(K key)- Returns a key-value mapping associated with the greatest key less than or equal to the given key, or null if there is no such key.
  • headMap(K toKey)- Returns a view of the portion of this map whose keys are strictly less than toKey.
  • higherKey(K key)- Returns the least key strictly greater than the given key, or null if there is no such key.
import java.util.Iterator;
import java.util.Map;
import java.util.NavigableSet;
import java.util.Set;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;

public class CSMDemo {
  public static void main(String[] args) {
    ConcurrentNavigableMap<String, String> cityMap = new ConcurrentSkipListMap<String, String>();
    cityMap.put("ND", "New Delhi");
    cityMap.put("MU", "Mumbai");
    cityMap.put("CH", "Chennai");
    cityMap.put("HD", "Hyderabad");
    System.out.println("---- Traversing the map-----");
    Set<Map.Entry<String, String>> citySet = cityMap.entrySet();
    // using for-each loop in Java 8
    citySet.forEach((m)->System.out.println("key " + m.getKey() + 
            " value " + m.getValue()));
        
    NavigableSet<String> reverseKeys = cityMap.descendingKeySet();
    // using iterator
    Iterator<String> itr = reverseKeys.iterator();
    System.out.println("---- Map keys in reverse order-----");
    while(itr.hasNext()){
      System.out.println("Key " + itr.next());
    }
        
    System.out.println("---- Floor entry-----");
    
    Map.Entry<String, String> tempMap = cityMap.floorEntry("II");
    System.out.println(tempMap);
        
    System.out.println("---- Head Map-----");
    ConcurrentNavigableMap<String, String> map = cityMap.headMap("MU");
    Set<Map.Entry<String, String>> set = map.entrySet();
    // using for-each loop in Java 8
    set.forEach((m)->System.out.println("key " + m.getKey() + 
                " value " + m.getValue()));
    
    System.out.println("---- Higher entry-----");
        
    tempMap = cityMap.higherEntry("II");
    System.out.println(tempMap);
  }
}

Output

---- Traversing the map-----
key CH value Chennai
key HD value Hyderabad
key MU value Mumbai
key ND value New Delhi
---- Map keys in reverse order-----
Key ND
Key MU
Key HD
Key CH
---- Floor entry-----
HD=Hyderabad
---- Head Map-----
key CH value Chennai
key HD value Hyderabad
---- Higher entry-----
MU=Mumbai

DescendingKeySet returns the keys in reverse order.

floorEntry() method returns the greatest key less than or equal to the given key. Here key is provided as "II" if you see greatest key less than or equal to "II" is "HD". Note here that key provided should not be a key already present in the Map ("II" is not a key present in the Map).

That's all for this topic ConcurrentSkipListMap in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ConcurrentHashMap in Java With Examples
  2. Java CyclicBarrier With Examples
  3. Java ArrayBlockingQueue With Examples
  4. How to Sort Elements in Different Order in TreeSet
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. Java ReentrantLock With Examples
  2. Difference between HashMap and ConcurrentHashMap in Java
  3. How to Iterate a HashMap of ArrayLists of String in Java
  4. HashMap Vs LinkedHashMap Vs TreeMap in Java
  5. Method Reference in Java
  6. Difference Between Abstract Class And Interface in Java
  7. super Keyword in Java With Examples
  8. Creating Custom Exception Class in Java

Tuesday, January 2, 2024

ConcurrentLinkedDeque in Java With Examples

ConcurrentLinkedDeque is another concurrent collection which is part of the java.util.concurrent package. Unlike many other concurrent collections like ConcurrentHashMap, CopyOnWriteArrayList which were added in Java 5 ConcurrentLinkedDeque was added in Java 7.

ConcurrentLinkedDeque in Java is an unbounded thread-safe Deque which stores its elements as linked nodes. Since it implements deque interface, ConcurrentLinkedDeque supports element insertion and removal at both ends. You will find methods like addFirst(), addLast(), getFirst(), getLast(), removeFirst(), removeLast() to facilitate operations at both ends.

Like most other concurrent collection implementations, this class does not permit the use of null elements.

Usage of ConcurrentLinkedDeque

A ConcurrentLinkedDeque in Java is an appropriate choice when many threads share access to a common collection as concurrent insertion, removal, and access operations execute safely across multiple threads.

Note that it doesn't block operations as done in the implementation of BlockingDequeue interface like LinkedBlockingDeque. So there are no putFirst(), takeFirst() or putLast(), takeLast() methods which will wait if required.

Java ConcurrentLinkedDeque Iterator

ConcurrentLinkedDeque's iterator is weakly consistent, returning elements reflecting the state of the queue at some point at or since the creation of the iterator. Iterators in ConcurrentLinkedDeque do not throw ConcurrentModificationException, and may proceed concurrently with other operations. Elements contained in the queue since the creation of the iterator will be returned exactly once.

ConcurrentLinkedDeque Java Example

Let's create a producer consumer using ConcurrentLinkedDeque. In this code there will be one producer thread putting element into the queue and two consumer threads retrieving elements from the queue. Note that producer thread will put 5 elements.

import java.util.Deque;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ConcurrentLDeQDemo {
  public static void main(String[] args) {
    //Buffer buffer = new Buffer();
    Deque<Integer> clDQue = new ConcurrentLinkedDeque<Integer>();
    ExecutorService executor = Executors.newFixedThreadPool(3);
    // Calling one producer
    executor.execute(new ProdTask(clDQue));
    // Calling two consumers
    executor.execute(new ConTask(clDQue));
    executor.execute(new ConTask(clDQue));
    executor.shutdown();
  }
}

/**
 * 
 */
class ProdTask implements Runnable{
  // Shared Deque object
  Deque<Integer> clDQue;
  ProdTask(Deque<Integer> clDQue){
    this.clDQue = clDQue;
  }
  @Override
  public void run() {
    for(int i = 0; i < 5; i++){
      clDQue.add(i);
    }
  }
}

/**
 * 
 */
class ConTask implements Runnable{
  Integer value;
  // Shared Deque object
  Deque<Integer> clDQue;
  ConTask(Deque<Integer> clDQue){
    this.clDQue = clDQue;
  }
  @Override
  public void run() {
    while ((value = clDQue.pollFirst()) != null) {
      if(value == null){
        System.out.println("No value to poll");
      }else{
        System.out.println("Consumer recd - " + value);
      }
    }
  }    
}

Output

Consumer recd - 0
Consumer recd - 1
Consumer recd - 2
Consumer recd - 3
Consumer recd - 4

That's all for this topic ConcurrentLinkedDeque in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ConcurrentLinkedQueue in Java With Examples
  2. Java BlockingQueue With Examples
  3. Java BlockingDeque With Examples
  4. ConcurrentHashMap in Java With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. Race Condition in Java Multi-Threading
  2. Lambda Expressions in Java 8
  3. @FunctionalInterface Annotation in Java
  4. Interface Static Methods in Java
  5. How HashMap Works Internally in Java
  6. Fail-Fast Vs Fail-Safe Iterator in Java
  7. Multi-Catch Statement in Java Exception Handling
  8. Print Odd-Even Numbers Using Threads And wait-notify Java Program

Thursday, March 2, 2023

ConcurrentSkipListSet in Java With Examples

ConcurrentSkipListSet in Java is a scalable concurrent set in Java which uses ConcurrentSkipListMap internally. Though concurrent collections like ConcurrentHashMap and CopyOnWriteArraySet were added in Java 1.5, ConcurrentSkipListSet and the similar map implementation ConcurrentSkipListMap were added in Java 1.6.

ConcurrentSkipListSet in Java

Since ConcurrentSkipListSet implements NavigableSet in Java, it is a sorted set just like TreeSet with added feature of being concurrent. Which essentially means it is a sorted data structure which can be used by multiple threads concurrently where as TreeSet is not thread safe.

The elements of the ConcurrentSkipListSet are kept sorted according to their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used.

Java ConcurrentSkipListSet constructors

  • ConcurrentSkipListSet()- Constructs a new, empty set that orders its elements according to their natural ordering.
  • ConcurrentSkipListSet(Collection<? extends E> c)- Constructs a new set containing the elements in the specified collection, that orders its elements according to their natural ordering.
  • ConcurrentSkipListSet(Comparator<? super E> comparator)- Constructs a new, empty set that orders its elements according to the specified comparator.
  • ConcurrentSkipListSet(SortedSet<E> s)- Constructs a new set containing the same elements and using the same ordering as the specified sorted set.Paste your text here.

Java ConcurrentSkipListSet performance

ConcurrentSkipListSet implementation provides expected average log(n) time cost for the contains, add, and remove operations and their variants. Insertion, removal, and access operations safely execute concurrently by multiple threads.

No Nulls in ConcurrentSkipListSet

ConcurrentSkipListSet does not permit the use of null elements, because null arguments and return values cannot be reliably distinguished from the absence of elements.

ConcurrentSkipListSet Java example

Let's see an example where we add some values in a ConcurrentSkipListSet and in the output it can be seen that the elements are sorted. In this example elements are of type String and for String natural ordering is ascending alphabetical order. So when you iterate the set you'll see it is in sorted same way.

Note that ConcurrentSkipListSet like any other set implementation i.e. HashSet can only store unique elements. Also, as mentioned internally it uses ConcurrentSkipListMap so when you call add method of ConcurrentSkipListSet it will in turn call putIfAbsent() method of the concurrentMap, that way element is stored only if it is not there already.

import java.util.Iterator;
import java.util.NavigableSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class CSSDemo {
  public static void main(String[] args) {
    NavigableSet<String> citySet = new ConcurrentSkipListSet<String>();
    citySet.add("New Delhi");
    citySet.add("Mumbai");
    citySet.add("Chennai");
    citySet.add("Hyderabad");
    
    System.out.println("---- Traversing the set-----");
    Iterator<String> itr = citySet.iterator();
    while(itr.hasNext()){
      System.out.println("Value -  " + itr.next());
    }
  }
}

Output

---- Traversing the set-----
Value -  Chennai
Value -  Hyderabad
Value -  Mumbai
Value -  New Delhi

Navigable methods in ConcurrentSkipListSet

As already mentioned ConcurrentSkipListSet in Java implements NavigableSet interface so it has many navigation methods returning the closest matches for given search targets. Let's see some of them in example code.

  • higher(E e)- Returns the least element in this set strictly greater than the given element, or null if there is no such element.
  • lower(E e)- Returns the greatest element in this set strictly less than the given element, or null if there is no such element.
  • tailSet(E fromElement)- Returns a view of the portion of this set whose elements are greater than or equal to fromElement.
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;

public class CSSDemo {
  public static void main(String[] args) {
    NavigableSet<String> citySet = new ConcurrentSkipListSet<String>();
    citySet.add("New Delhi");
    citySet.add("Mumbai");
    citySet.add("Chennai");
    citySet.add("Hyderabad");
    
    System.out.println("---- Traversing the set-----");
    Iterator<String> itr = citySet.iterator();
    while(itr.hasNext()){
      System.out.println("Value -  " + itr.next());
    }
        
    System.out.println("Higher - " + citySet.higher("C"));    
    System.out.println("Lower - " + citySet.lower("Mumbai"));    
    System.out.println("---- Tail Set -----");
    
    Set<String> set = citySet.tailSet("Hyderabad");    
    itr = set.iterator();
    while(itr.hasNext()){
      System.out.println("Value -  " + itr.next());
    }
  }
}

Output

---- Traversing the set-----
Value -  Chennai
Value -  Hyderabad
Value -  Mumbai
Value -  New Delhi
Higher - Chennai
Lower - Hyderabad
---- Tail Set -----
Value -  Hyderabad
Value -  Mumbai
Value -  New Delhi

Here higher as the description says is returning the least element in this set strictly greater than the given element. Since given element is "C" so returned value is "Chennai". Note that passed element doesn't have to be the one already present in set as here "C" is passed which is not an element of the Set.

lower as the description says is returning the greatest element in this set strictly less than the given element. Passed element is "Mumbai" so that returned element is "Hyderabad".

That's all for this topic ConcurrentSkipListSet in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ConcurrentHashMap in Java With Examples
  2. CopyOnWriteArraySet in Java With Examples
  3. Java ArrayBlockingQueue With Examples
  4. Java CountDownLatch With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. How to Sort Elements in Different Order in TreeSet
  2. How to Sort HashSet in Java
  3. Difference Between Comparable and Comparator in Java
  4. Interface Default Methods in Java
  5. Java ThreadLocal Class With Examples
  6. Deadlock in Java Multi-Threading
  7. static Import in Java With Examples
  8. Difference Between throw And throws in Java

Wednesday, August 24, 2022

Difference Between HashMap And ConcurrentHashMap in Java

In this post we'll see the differences between ConcurrentHashMap and HashMap in Java which is also a good Java interview question.

ConcurrentHashMap was added in Java 5 as an alternative to HashTable to improve the performance of the (key, value) pair kind of data structure while still keeping it thread safe. On the other hand HashMap in Java is not synchronized so provides better performance but it is not thread safe.

HashMap Vs ConcurrentHashMap in Java

  1. First and foremost difference between HashMap and ConcurrentHashMap in Java is of course thread safety. ConcurrentHashMap is thread safe and fit for use in a multi-threaded environment whereas HashMap is not thread safe.
  2. Second difference is about how these data structures synchronize. HashMap can be synchronized using the Collections.synchronizedMap() method but that synchronizes all the methods of the HashMap on a common lock and effectively reduces it to a data structure where one thread can enter at a time.

    In ConcurrentHashMap synchronization is done a little differently. Rather than locking every method on a common lock, ConcurrentHashMap uses separate lock for separate buckets thus locking only a portion of the Map.

    By default there are 16 buckets and also separate locks for separate buckets. So the default concurrency level is 16. That means theoretically any given time 16 threads can access ConcurrentHashMap if they all are going to separate buckets.

  3. In ConcurrentHashMap performance is further improved by providing read access concurrently without any blocking. Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove).
  4. HashMap allows one null as key but ConcurrentHashMap doesn't allow null as key.

  5. Performace wise HashMap is better as there is no synchronization.

    In case HashMap has to be used in a multi-threaded environment and there is a need to use Collections.SynchronizedMap() method then ConcurrentHashMap() is a better choice as ConcurrentHashMap still gives a chance to more than one thread to access map thus improving performance.

  6. Iterator provided by ConcurrentHashMap is fail-safe which means it will not throw ConcurrentModificationException if the underlying structure is changed during iteration.

    Iterator provided by HashMap is fail-fast as it throws a ConcurrentModificationException if the underlying collection is structurally modified at any time after the iterator is created.

That's all for this topic Difference Between HashMap And ConcurrentHashMap in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ConcurrentHashMap in Java With Examples
  2. Difference Between ArrayList And CopyOnWriteArrayList in Java
  3. Java Semaphore With Examples
  4. Java ReentrantLock With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. Difference Between Comparable and Comparator in Java
  2. How to Sort HashSet in Java
  3. Lambda Expression Examples in Java
  4. How to Iterate a HashMap of ArrayLists of String in Java
  5. Race Condition in Java Multi-Threading
  6. Interface Default Methods in Java
  7. Java ThreadLocal Class With Examples
  8. How to Read File From The Last Line in Java

Wednesday, May 5, 2021

CopyOnWriteArrayList in Java With Examples

This post talks about CopyOnWriteArrayList in Java residing in java.util.concurrent package. It is a thread safe implementation of the List interface.


Synchronized List options in Java

Though we have an option to synchronize the collections like List or Set using synchronizedList or synchronizedSet methods respectively of the Collections class but there is a drawback to this synchronization; very poor performance as the whole collection is locked and only a single thread can access it at a given time.

Java also has a Vector class as a thread-safe alternative to List but that thread safety is achieved by synchronizing all the methods of the Vector class, which again results in poor performance.

CopyOnWriteArrayList in Java

From Java 5 CopyOnWriteArrayList is introduced as a thread-safe variant of ArrayList. It is designed for concurrent access from multiple threads. CopyOnWriteArrayList provides a thread-safe alternative for ArrayList, same way ConcurrentHashMap provides a thread-safe alternative for HashMap and CopyOnWriteArraySet for HashSet.

Thread safety in CopyOnWriteArrayList

Thread safety in CopyOnWriteArrayList is achieved by making a fresh copy of the underlying array with every mutative operations (add, set, and so on). It is evident from the name also "Copy on write"; whenever value is changed create a copy.

You may argue that this way of creating a fresh copy whenever any mutative operation is performed must be very costly. Yes it is, that is why using CopyOnWriteArrayList provides better performance in scenarios where there are more iterations of the list than mutations.

That brings us to the second point "snapshot style" iterator in CopyOnWriteArrayList.

CopyOnWriteArrayList has a fail-safe iterator

Iterator returned by Java CopyOnWriteArrayList is fail-safe, it uses a reference to the state of the array at the point that the iterator was created. You know by now any mutation will result in a fresh copy of the underlying array. Thus the array that the iterator has a reference to never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException.

The iterator will not reflect additions, removals, or changes to the list since the iterator was created thus it is also known as "snapshot style" iterator.

Element-changing operations on iterators themselves (remove, set, and add) are not supported. These methods throw UnsupportedOperationException.

Since iterator is not affected by the mutations thus multiple threads can iterate the collection without interference from one another or from threads wanting to modify the collection.

Java CopyOnWriteArrayList constructors

  • CopyOnWriteArrayList()- This constructor Creates an empty list.
  • CopyOnWriteArrayList​(E[] toCopyIn)- Creates a list holding a copy of the given array.
  • CopyOnWriteArrayList​(Collection<? extends E> c)- Creates a list containing the elements of the specified collection, in the order they are returned by the collection's iterator.

CopyOnWriteArrayList Java Example

Let's see a simple Java example creating CopyOnWriteArrayList and adding elements to it.

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteALDemo {
  public static void main(String[] args) {
    List<String> numList = new CopyOnWriteArrayList<String>();
    numList.add("1");
    numList.add("2");
    numList.add("3");
    numList.add("4");
    // Displaying CopyOnWriteArrayList elements
    for(String num : numList){
      System.out.println("Number- " + num);
    }
  }
}

Output

Number- 1
Number- 2
Number- 3
Number- 4

Java CopyOnWriteArrayList iterator Example

Let's see "snapshot style" iterator concept of CopyOnWriteArrayList in Java with an example.

First let's use ArrayList with 2 threads accessing it concurrently. One of the thread tries to structurally modified the ArrayList while second thread is iterating it. This should result in a ConcurrentModificationException.

public class FailFastDemo {
  public static void main(String[] args) {
    List<String> numList = new ArrayList<String>();
    numList.add("1");
    numList.add("2");
    numList.add("3");
    numList.add("4");
        
    //This thread will iterate the list
    Thread thread1 = new Thread(){ 
      public void run(){ 
        try{ 
          Iterator<String> i = numList.iterator(); 
          while (i.hasNext()){ 
            System.out.println(i.next()); 
            // Using sleep to simulate concurrency
            Thread.sleep(1000); 
          }     
        }catch(ConcurrentModificationException e){ 
          System.out.println("thread1 : Concurrent modification detected 
            on this list"); 
          e.printStackTrace();
        }catch(InterruptedException e){
          
        } 
      } 
    }; 
    thread1.start(); 
        
    // This thread will try to add to the collection,
    // while the collection is iterated by another thread.
    Thread thread2 = new Thread(){ 
      public void run(){ 
        try{ 
          // Using sleep to simulate concurrency
          Thread.sleep(2000);
          // adding new value to the shared list
          numList.add("5"); 
          System.out.println("new value added to the list"); 
        }catch(ConcurrentModificationException e){ 
          System.out.println("thread2 : Concurrent modification detected 
                  on the List"); 
        } catch(InterruptedException e){}
      } 
    }; 
    thread2.start(); 
  }
}

Output

1
2
new value added to the list
thread1 : Concurrent modification detected on this list
java.util.ConcurrentModificationException
 at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
 at java.util.ArrayList$Itr.next(Unknown Source)
 at org.netjs.prog.FailFastDemo$1.run(FailFastDemo.java:24)

Here it can be seen that the ConcurrentModificationException is thrown because the list is changed by a thread while it has been iterated by another thread.

Now in the same code change the ArrayList to CopyOnWriteArrayList. Also added one sysout after adding new element to the list.

public class FailFastDemo {
  public static void main(String[] args) {
    List<String> numList = new CopyOnWriteArrayList<String>();
    numList.add("1");
    numList.add("2");
    numList.add("3");
    numList.add("4");
        
    //This thread will iterate the list
    Thread thread1 = new Thread(){ 
      public void run(){ 
        try{ 
          Iterator<String> i = numList.iterator(); 
          while (i.hasNext()){ 
            System.out.println(i.next()); 
            // Using sleep to simulate concurrency
            Thread.sleep(1000); 
          }     
        }catch(ConcurrentModificationException e){ 
          System.out.println("thread1 : Concurrent modification detected 
            on this list"); 
          e.printStackTrace();
        }catch(InterruptedException e){
                    
        } 
      } 
    }; 
    thread1.start(); 
        
    // This thread will try to add to the collection,
    // while the collection is iterated by another thread.
    Thread thread2 = new Thread(){ 
      public void run(){ 
        try{ 
          // Using sleep to simulate concurrency
          Thread.sleep(2000);
          // adding new value to the shared list
          numList.add("5"); 
          System.out.println("new value added to the list"); 
          System.out.println("List " + numList);
        }catch(ConcurrentModificationException e){ 
          System.out.println("thread2 : Concurrent modification detected 
           on the List"); 
        } catch(InterruptedException e){}
      } 
    }; 
    thread2.start();    
  }
}

Output

1
2
3
new value added to the list
List [1, 2, 3, 4, 5]
4

Here ConcurrentModificationException is not thrown as CopyOnWriteArrayList is used now. Also note that, though one of the thread adds a new element and at that time the list prints all the elements from 1-5. But the iterator has the reference to the old copy of the list and it prints from 1-4.

Points to note

  • CopyOnWriteArrayList in Java provides a thread-safe alternative to the normal ArrayList.
  • In CopyOnWriteArrayList thread safety is achieved in a different way from a thread safe collection like Vector. In CopyOnWriteArrayList fresh copy of the underlying array is created with every mutative operations (add, set, and so on).
  • Because of this approach CopyOnWriteArrayList gives better performance in case there are more threads iterating the list than mutating it. Several threads can iterate CopyOnWriteArrayList concurrently.
  • CopyOnWriteArrayList's iterator is fail-safe and guaranteed not to throw ConcurrentModificationException.
  • CopyOnWriteArrayList's iterator uses a reference to the state of the array at the point that the iterator was created.
  • The iterator will not reflect additions, removals, or changes to the list since the iterator was created thus it is also known as "snapshot style" iterator.
  • All elements are permitted, including null.

That's all for this topic CopyOnWriteArrayList in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ConcurrentHashMap in Java With Examples
  2. Java CyclicBarrier With Examples
  3. Difference Between ArrayList And CopyOnWriteArrayList in Java
  4. Fail-Fast Vs Fail-Safe Iterator in Java
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. How ArrayList Works Internally in Java
  2. Java Collections Interview Questions And Answers
  3. How to Iterate a HashMap of ArrayLists of String in Java
  4. Java Program to Convert a File to Byte Array
  5. static reference to the non-static method or field error
  6. Race Condition in Java Multi-Threading
  7. Java ThreadLocal Class With Examples
  8. Interface Default Methods in Java

Saturday, April 10, 2021

ConcurrentLinkedQueue in Java With Examples

ConcurrentLinkedQueue in Java implements Queue interface and it was added in Java 5 along with other concurrent utilities like CyclicBarrier, CountDownLatch, Semaphore, ConcurrentHashMap etc.

ConcurrentLinkedQueue in Java is an unbounded thread-safe queue which stores its elements as linked nodes. This queue orders elements FIFO (first-in-first-out). The head of the queue is the element that has been on the queue the longest time. The tail of the queue is the element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue.

Like most other concurrent collection implementations, ConcurrentLinkedQueue class does not permit the use of null elements.

Usage of ConcurrentLinkedQueue in Java

A ConcurrentLinkedQueue is an appropriate choice when many threads will share access to a common collection. Note that it doesn't block operations as it is done in the implementations of BlockingQueue interface like ArrayBlockingQueue, LinkedBlockingQueue. So there are no put() or take() methods which will wait if required.

Java ConcurrentLinkedQueue constructors

  • ConcurrentLinkedQueue()- Creates a ConcurrentLinkedQueue that is initially empty.
  • ConcurrentLinkedQueue​(Collection<? extends E> c)- Creates a ConcurrentLinkedQueue initially containing the elements of the given collection, added in traversal order of the collection's iterator.

Friday, January 1, 2021

Difference Between ArrayList And CopyOnWriteArrayList in Java

CopyOnWriteArrayList was added in Java 5 as a thread-safe alternative to ArrayList, which is one of the most used collection along with HashMap. In this post we'll see the differences between the CopyOnWriteArrayList and ArrayList in Java.

ArrayList Vs CopyOnWriteArrayList in Java

  1. First and foremost difference between CopyOnWriteArrayList and ArrayList is of course thread safety. ArrayList is not thread-safe whereas CopyOnWriteArrayList is thread-safe and fit for use in multi-threaded environment.

    This thread safety in CopyOnWriteArrayList is achieved by making a fresh copy of the underlying array with every mutative operations (add, set, and so on).

  2. Iterator returned by ArrayList is fail-fast. Which means, if the underlying collection is structurally modified in any way except through the iterator's own remove or add methods, it will throw ConcurrentModificationException.

    Iterator returned by CopyOnWriteArrayList is fail-safe. Iterators for the CopyOnWriteArrayList uses a reference to the state of the array at the point that the iterator was created. Since any mutation will result in a fresh copy of the underlying array. Thus the array that the iterator has a reference to never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException.

    Let's see this difference with an example, here we'll have an ArrayList which will be iterated. Simultaneously a new thread is created which will try to add an element to that ArrayList.

    public class CADemo {
      public static void main(String[] args) {
        List<Integer> numList = new ArrayList<Integer>();
        // Adding 5 elements to the set
        for(int i=1;i<=5;i++) {
          numList.add(i);
        }
            
        // Creating new thread
        new Thread(new Runnable(){
          @Override
          public void run() {
            try {
              // introducing some delay
              Thread.sleep(150);
            } catch (InterruptedException e) {
              Thread.currentThread().interrupt();
            }
            // add new element to the set
            numList.add(6);
            System.out.println("" + numList);
          }
        }).start();
                    
        // get an iterator
        Iterator<Integer> itr = numList.iterator();
        while(itr.hasNext()){
          Integer i = itr.next();
          try {
            Thread.sleep(30);
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
          //itr.remove();
          System.out.println("" + i);
        }
      }
    }
    

    Output

    1
    2
    3
    4
    5
    [6]
    Exception in thread "main" java.util.ConcurrentModificationException
     at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
     at java.util.ArrayList$Itr.next(Unknown Source)
     at org.netjs.prgrm.CADemo.main(CADemo.java:37)
    

    Here it can be seen that the ConcurrentModificationException is thrown as there is an attempt to add an element to the ArrayList while it is iterated.

    Example code with CopyOnWriteArrayList

    Now let's changed the ArrayList with CopyOnWriteArrayList.

    public class CADemo {
      public static void main(String[] args) {
        List<Integer> numList = new CopyOnWriteArrayList<Integer>();
        // Adding 5 elements to the set
        for(int i=1;i<=5;i++) {
          numList.add(i);
        }
            
        // Creating new thread
        new Thread(new Runnable(){
          @Override
          public void run() {
            try {
              // introducing some delay
              Thread.sleep(150);
            } catch (InterruptedException e) {
              Thread.currentThread().interrupt();
            }
            // add new element to the set
            numList.add(6);
            System.out.println("" + numList);
          }
        }).start();
            
            
        // get an iterator
        Iterator<Integer> itr = numList.iterator();
        while(itr.hasNext()){
          Integer i = itr.next();
          try {
            Thread.sleep(30);
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
          //itr.remove();
          System.out.println("" + i);
        }
      }
    }
    

    Output

    1
    2
    3
    4
    [1, 2, 3, 4, 5, 6]
    5
    

    Here it can be seen that the ConcurrentModificationException is not thrown. Also, since iterator gets its own copy so it doesn't reflect the change made to the CopyOnWriteArrayList while iteration is done.

  3. Performance wise ArrayList is faster as it is not synchronized and there is no added burden of thread-safety. CopyOnWriteArrayList is comparatively slower and if there are lots of writes by various threads that will degrade the performance of the CopyOnwriteArrayList as there will be copies made per mutation.

That's all for this topic Difference Between ArrayList And CopyOnWriteArrayList in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference Between HashMap And ConcurrentHashMap in Java
  2. Difference Between CountDownLatch And CyclicBarrier in Java
  3. Difference Between ReentrantLock and Synchronized in Java
  4. CopyOnWriteArraySet in Java With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. How to Loop or Iterate an Arraylist in Java
  2. How to Join Lists in Java
  3. Fail-Fast Vs Fail-Safe Iterator in Java
  4. Java BlockingQueue With Examples
  5. Lambda Expressions in Java 8
  6. Race Condition in Java Multi-Threading
  7. Deadlock in Java Multi-Threading
  8. Java Pass by Value or Pass by Reference

Sunday, December 6, 2020

CopyOnWriteArraySet in Java With Examples

In Java 5 many concurrent collection classes are added as a thread safe alternative for their normal collection counterparts which are not thread safe. Like ConcurrentHashMap as a thread safe alternative for HashMap, CopyOnWriteArrayList as a thread safe alternative for ArrayList. Same way CopyOnWriteArraySet in Java is added as a thread safe alternative for HashSet in Java.

CopyOnWriteArraySet class in Java

CopyOnWriteArraySet implements the Set interface (Actually it extends the AbstractSet class which in turn implements the set interface). Since CopyOnWriteArraySet implements the Set interface so basic functionality of the Set that only unique elements can be added applies to CopyOnWriteArraySet too.