Showing posts with label Synchronized Map. Show all posts
Showing posts with label Synchronized Map. Show all posts

How to convert HashMap to Synchronized Map ?

In this tutorial we will see about how to convert HashMap to synchronized Map. As we know already that HashMap is not synchronized by default.

Synchronize is nothing but making the HashMap to thread safe and by multi-threading environment only one user can remove or edit the Map values. For example if we are using HashMap only for read operation then making synchronized Map is not necessary. Only when multi users or more threads tries to update or remove same key or value from HashMap then we need to make HashMap synchronized for thread safe purpose.

In Java we can do this very easily by using java.util.Collections class as like give below.



Map<String, Object> myMap = new HashMap<String, Object>();
.
.
.  
.
myMap = Collections.synchronizedMap(myMap);


From above code snippet we have declared myMap as HashMap and later in below code we have converted same HashMap instance to synchronized Map. Since this is a simple interview question which asked in 2 to 3 yrs experience level. Hope you are clear now how to convert HashMap to synchronized Map.

Above we have seen how to convert HashMap to SynchronizedMap. Even by converting SynchronizedMap its not guarantee that values will be thread safe we are editing or removing on same Object using multiple Thread. As per  Collections#synchronizedMap() in Oracle docs we need to make operations on Map with synchronized block as mentioned in Oracle docs.  

Lets see all scenarios with details example of 

  1. Accessing updated HashMap without converting to SynchronizedMap under Multi Threading.
  2. Accessing updated HashMap just converting to SynchronizedMap under Multi Threading.
  3. Accessing updated HashMap with converted to SynchronizedMap & Synchronized block under Multi Threading.

Example - 1 : Accessing updated HashMap without converting to SynchronizedMap under Multi Threading.


public class HashMapTest implements Runnable{
 
 // Initializing new HashMap
 private Map<String, String> myMap = new HashMap<String, String>();
 
 public void run() {
  String threadName = Thread.currentThread().getName();
  String oldValue = myMap.get("myKey");
  String newValue = oldValue+threadName;
  myMap.put("myKey", newValue);
  System.out.println(threadName+" : "+myMap.get("myKey"));
 }
 
 public static void main(String[] args) {
  HashMapTest obj = new HashMapTest();
  
  // Adding values into HashMap
  obj.addValues();
  
  // Creating multiple Thread and starting
  for(int i=0;i<5;i++){
   new Thread(obj).start();
  }
  
 }
 public void addValues(){
  myMap.put("myKey", "Java Discover - ");
 }
}


OUTPUT:


Thread-0 : Java Discover - Thread-3
Thread-1 : Java Discover - Thread-3
Thread-2 : Java Discover - Thread-3
Thread-3 : Java Discover - Thread-3
Thread-4 : Java Discover - Thread-3




In above example we have placed 1 value in HashMap and in run() method we trying to upend Thread name to existing value. Each thread names need to be upended in the value, where as we can see only Thread-3 has upended with original value. Remaining 4 Thread names are not updated correctly. Next example lets see just by converting HashMap to SynchronizedMap.



Example - 2 : Accessing updated HashMap just converting to SynchronizedMap under Multi Threading.


public class HashMapTest implements Runnable{
 
 // Initializing new HashMap
 private Map<String, String> myMap = new HashMap<String, String>();
 
 public void run() {
  String threadName = Thread.currentThread().getName();
  String oldValue = myMap.get("myKey");
  String newValue = oldValue+threadName;
  myMap.put("myKey", newValue);
  System.out.println(threadName+" : "+myMap.get("myKey"));
 }
 
 public static void main(String[] args) {
  HashMapTest obj = new HashMapTest();
  
  // Adding values into HashMap
  obj.addValues();
  
  // Converting HashMap to Synchronized Map 
  obj.convertMapToSynMap();
  
  // Creating multiple Thread and starting
  for(int i=0;i<5;i++){
   new Thread(obj).start();
  }
  
 }
 public void convertMapToSynMap(){
  myMap = Collections.synchronizedMap(myMap);
 }
 public void addValues(){
  myMap.put("myKey", "Java Discover - ");
 }
}


OUTPUT:


Thread-0 : Java Discover - Thread-1
Thread-1 : Java Discover - Thread-1
Thread-2 : Java Discover - Thread-1Thread-2
Thread-3 : Java Discover - Thread-1Thread-2Thread-3
Thread-4 : Java Discover - Thread-1Thread-2Thread-3Thread-4



Even by making SynchronizedMap we are getting wrong output when mutiple thread trying to update same Map key value. In above code we can see Thread-0 is missing. Next lets see how to thread safe when we edit under multi threading on same object. 

Example - 3 : Accessing updated HashMap with converted to SynchronizedMap & Synchronized block under Multi Threading.


public class HashMapTest implements Runnable{
 
 // Initializing new HashMap
 private Map<String, String> myMap = new HashMap<String, String>();
 
 public void run() {
  String threadName = Thread.currentThread().getName();
  // Synchronized block 
  synchronized (myMap) {
   String oldValue = myMap.get("myKey");
   String newValue = oldValue+threadName;
   myMap.put("myKey", newValue);
  }  
  System.out.println(threadName+" : "+myMap.get("myKey"));
 }
 
 public static void main(String[] args) {
  HashMapTest obj = new HashMapTest();
  
  // Adding values into HashMap
  obj.addValues();
  
  // Converting HashMap to Synchronized Map 
  obj.convertMapToSynMap();
  
  // Creating multiple Thread and starting
  for(int i=0;i<5;i++){
   new Thread(obj).start();
  }
  
 }
 public void convertMapToSynMap(){
  myMap = Collections.synchronizedMap(myMap);
 }
 public void addValues(){
  myMap.put("myKey", "Java Discover - ");
 }
}

OUTPUT:


Thread-0 : Java Discover - Thread-0Thread-1
Thread-1 : Java Discover - Thread-0Thread-1
Thread-2 : Java Discover - Thread-0Thread-1Thread-2Thread-3
Thread-3 : Java Discover - Thread-0Thread-1Thread-2Thread-3
Thread-4 : Java Discover - Thread-0Thread-1Thread-2Thread-3Thread-4

Now we see all Thread names are upended correctly from 0 to 5. Order doesn't matter since Thread will called according priority.