Need of Concurrent Collections in Java


Concurrent Collections in Java

Java is a well-known computer language that supports concurrency and multithreading. Developers can use the synchronization keyword to guarantee correct synchronization between threads. Additionally, a variety of collections that can be used to hold and manipulate data are offered by Java's collection framework.

The synchronized keyword can be used by coders to make these collections thread-safe. The efficient and secure execution of programs involving numerous threads operating concurrently depends on this capability.

What Is the Need of Concurrent Collections in Java?

ArrayList, LinkedList, HashSet, HashMap, and LinkedHashMap are just a few of the classes in Java's collections structure that aren't intended to be used safely in multi-threaded environments.

This implies that the outcomes need to be more accurate if we use these collections in a scenario where multiple threads are accessing them concurrently. We require thread-safe classes that numerous threads can access without causing any problems to address this issue.

Although we can synchronize these collections using methods like Collections.synchronizedList(list), this is not the best solution.

Even if other threads only need to read the data, when we use this method, only one thread can access the complete list at once. This could make the mechanism work less efficiently. We must use concurrent collections to manage concurrent access more effectively. These collections are created so numerous threads can access them simultaneously without issues.

ConcurrentHashMap

ConcurrentHashMap is a widely used collection class in Java 5. It's popular because it offers a concurrent option to Hashtable or Synchronized Map classes, allowing for a higher level of concurrency by using fine-grained locking.

With ConcurrentHashMap, many readers can access the Map at the same time, while a portion of the Map gets locked for write operation, depending on the concurrency level of the Map. This helps provide better scalability than synchronized maps.

Algorithm

  • Step 1 − Import the java.util.concurrent.* package. This contains classes for concurrency utilities.

  • Step 2 − Define a class called MyConcurrentHashMap with the main method. This is the entry point for the program.

  • Step 3 − Create a new instance of the ConcurrentHashMap class called concurrentHashMap.

  • Step 4 − Add three key-value pairs to the concurrentHashMap using the put method. Each key-value pair represents a product ID and its corresponding product name.

  • Step 5 − Print the contents of the concurrentHashMap to the console using the println method. This will output the contents of the concurrentHashMap in an unordered manner.

Example 1

This program demonstrates how to use the ConcurrentHashMap class in Java.

import java.util.concurrent.*;
public class MyConcurrentHashMap {
   public static void main(String[] args){
      ConcurrentHashMap<String, String> concurrentHashMap
      = new ConcurrentHashMap<>();
      concurrentHashMap.put("P001", "Apple Iphone");
      concurrentHashMap.put("P002", "Samsung Smartphone");
      concurrentHashMap.put("P003", "Google Pixel");
      System.out.println(concurrentHashMap);
   }
}

Output

{P001=Apple Iphone, P003=Google Pixel, P002=Samsung Smartphone}

BlockingQueue

A popular collection class in Java 5 that aids in the producer-consumer design pattern implementation is the BlockingQueue. It is simple to use and has built-in blocking support for the put() and take() functions.

If the queue is filled, the put() method will wait; if the queue is empty, the take() method will wait. As a result, it is simpler to control the movement of materials between producers and customers.

ArrayBlockingQueue and LinkedBlockingQueue are two different versions of BlockingQueue available in Java 5. The first-in, first-out (FIFO) elemental arrangement is used by both of them. While LinkedBlockingQueue is potentially bounded, ArrayBlockingQueue is bound and supported by an array.

CopyOnWriteArrayList

CopyOnWriteArrayList is a data structure that creates a cloned copy of the underlying ArrayList every time there is an update operation. This cloned copy is automatically synchronized with the original ArrayList by the JVM. As a result, threads performing read operations are not affected.

However, this approach can be expensive because a cloned copy is created for every update operation. Therefore, CopyOnWriteArrayList is the best option if the frequent operation is read operation. This data structure is a thread-safe version of ArrayList and allows insertion of duplicates, null values, and heterogeneous objects while preserving their order.

One important thing to note about CopyOnWriteArrayList is that its Iterator cannot perform a remove operation, and calling the add() and set() methods on the iterator will result in an UnsupportedOperationException runtime exception. Also, the Iterator of CopyOnWriteArrayList will never throw a ConcurrentModificationException.

Algorithm

  • Step 1 − The program adds three components to an object called "l" belonging to the CopyOnWriteArrayList class. Even as the primary thread continues to loop through the list, a new thread is initiated to append a fresh element to it.

  • Step 2 − To safeguard the iteration process from any changes the child thread may make to the list, the software relies on the CopyOnWriteArrayList class.

  • Step 3 − After printing every element in the list, including the child thread's addition of the "Z" element, the complete list is printed in sequence.

Example 2

The below program demonstrates the use of CopyOnWriteArrayList class to ensure thread safety while iterating over a list.

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class ConcurrentDemo extends Thread {
   static CopyOnWriteArrayList<String> l
   = new CopyOnWriteArrayList<String>();
   public void run(){
      // Child thread trying to
      // add new element in the
      // Collection object
      l.add("Z");
   }
   public static void main(String[] args)
   throws InterruptedException{
      l.add("W");
      l.add("X");
      l.add("Y");
      
      // We create a child thread
      // that is going to modify
      // ArrayList l.
      ConcurrentDemo t = new ConcurrentDemo();
      t.start();
      Thread.sleep(1000);
      
      // Now we iterate through
      // the ArrayList and get
      // exception.
      Iterator itr = l.iterator();
      while (itr.hasNext()) {
         String s = (String)itr.next();
         System.out.println(s);
         Thread.sleep(1000);
      }
      System.out.println(l);
   }
}

Output

W
X
Y
Z
[W, X, Y, Z]

Conclusion

When using multiple threads with collections in Java, using thread-safe collections like ConcurrentHashMap, BlockingQueue, and CopyOnWriteArrayList is crucial to avoid data inconsistency and improve program efficiency. These collections offer various features to meet different concurrency needs and can enhance the performance of Java applications involving multithreading.

Updated on: 15-May-2023

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements