Monday, May 30, 2016

Internal representation of Thread join()


package com.javadsalgo;

class ThreadJoinDemo extends Thread {
     static ThreadJoinDemo thread1;

     public void run() {
           try {
           synchronized (thread1) {
           System.out.println(Thread.currentThread().getName()+ "                  acquired a lock on thread1");
           System.out.println("Going to sleep for 5 minutes");
           System.out.println("If thread1 is locked ?                              "+Thread.holdsLock(thread1));
           Thread.sleep(5000);
           System.out.println(Thread.currentThread().getName()+ "                  completed");
           // System native call invokes thread1.notifyAll(), so return            goes to main thread
                }
           } catch (InterruptedException e) {
       }
     }

     public static void main(String[] ar) throws Exception {
           thread1 = new ThreadJoinDemo();
           thread1.setName("thread1");
           thread1.start();

           synchronized (thread1) {
           // main thread will enter and acquire the lock on thread1.
           System.out.println(Thread.currentThread().getName() + "                  acquired a lock on inner thread1");
           System.out.println("Going to sleep for 2 minutes");
           Thread.sleep(2000);
           System.out.println("If thread1 is locked                                ?"+Thread.holdsLock(thread1));
           /*
           * join() internally calling thread1.wait(),which means                    main thread executing the code will release the lock on                  thread1 and go on waiting state...Entered to run()*/
           thread1.join();
           System.out.println(Thread.currentThread().getName() + "                  completed");
           }
           System.out.println("If thread1 is locked                                ?"+Thread.holdsLock(thread1));
     }
}

Output:

main acquired a lock on inner thread1
Going to sleep for 2 minutes
If thread1 is locked ?true
thread1 acquired a lock on thread1
Going to sleep for 5 minutes
If thread1 is locked ?true
thread1 completed
main completed
If thread1 is locked ?false

Who call notify/notifyAll in case of thread waiting on join method?
After run() method of thread is completed, it doesn't mean thread task is completed, 
It has to do many other tasks like 
  1. Destroying the associated stack, 
  2. Setting the necessary threadStatus etc.
One of the task is notifying the waiting threads, So that Thread waiting on join() method will be notified that thread has completed its task and joined threads can resume.

Above task are executed inside native thread call, so it won't be visible in java thread API.

References: http://javabypatel.blogspot.in/2016/05/how-thread-join-method-works-internally-iava.html

ConcurrentHashMap vs Hashtable vs Synchronized Map


v ConcurrentHashMap performs better than earlier two because it only locks a portion of Map, instead of whole Map, which is the case with Hashtable and synchronized Map.

v CHM allows concurred read operations and same time, maintains integrity by synchronizing write operations. 

v ConcurrentHashMap is best suited when you have multiple readers and few writers. 

v During update operation, ConcurrentHashMap only lock a portion of Map instead of whole Map.
"Concurrency level", allows ConcurrentHashMap to partition Map.

v ConcurrentHashMap partitions Map into different parts based on concurrency level and locking only a portion of Map during updates. Default concurrency level is 16, and accordingly Map is divided into 16 part and each part is governed with different lock. This means, 16 thread can operate on Map simultaneously, until they are operating on different part of Map. This makes ConcurrentHashMap high performance despite keeping thread-safety intact. 

v Another important point to remember is iteration over CHM, Iterator returned by keySet of ConcurrentHashMap are weekly consistent and they only reflect state of ConcurrentHashMap and certain point and may not reflect any recent change. Iterator of ConcurrentHashMap's keySet area also fail-safe and doesn’t throw ConcurrentModificationExceptoin.

v Default concurrency level is 16 and can be changed.

v ConcurrentHashMap doesn't allow null as key or value.

v ConcurrentHashMap provides putIfAbsent(key, value) which does same thing but atomically and thus eliminates below race condition.

synchronized(map){
  if (map.get(key) == null){
      return map.put(key, value);
  } else{
      return map.get(key);
  }
}

HashMap
Collections.SynchronizedMap
ConcurrentHashMap
No Synchronization
Use very simple synchronization, which means that only one thread can access the map at the same time.
Allow parallel read access by multiple threads without synchronization and, more importantly, provides an Iterator that requires no synchronization and even allows the Map to be modified during interation
Null key-value pair allowed
No Null Key-value pair
No Null Key-value pair
No Lock Mechanism . HashTable locks the object
Locks the whole map
Locks the segment out of 16 segments. Locks bucket only
Not thread-Safe
Thread-Safe
Thread-Safe
Fail-fast Iterator
Fail-fast Iterator
Fail-safe Iterator

Why Concurrent HashMap doesn’t allow null key ?

The main reason that nulls aren't allowed in ConcurrentMaps (ConcurrentHashMaps, ConcurrentSkipListMaps) because there will be ambiguities that may be just barely tolerable in non-concurrent maps can't be accommodated.

The main one is that if map.get(key) returns null, you can't detect whether the key explicitly maps to null vs the key isn't mapped.

if (key == null || value == null) throw new NullPointerException();
public class ConcurrentHashMapDemo {

     public static void main(String[] args) {
           ConcurrentHashMap<String, String> chm= new ConcurrentHashMap<>();
           chm.put(null,"Paras");
           System.out.println(chm.get(null));
     }
}

Output:

Exception in thread "main" java.lang.NullPointerException
at java.util.concurrent.ConcurrentHashMap.putVal(Unknown Source)
at java.util.concurrent.ConcurrentHashMap.put(Unknown Source)
at com.javadsalgo.ConcurrentHashMapDemo.main(ConcurrentHashMapDemo.java:9)

In a non-concurrent map, you can check this via map.contains(key), but in a concurrent one, the map might have changed between calls.

The code is like this :

    
if (map.containsKey(k)) {
     return map.get(k);
else {
     throw new KeyNotPresentException();
}

It might be possible that key k might be deleted in between the get(k) and containsKey(k) calls.
As a result, the code will return null as opposed to KeyNotPresentException (Expected Result if key is not present).


The Null key and value allowed in HashMap because there is no Concurrent access.

Saturday, May 28, 2016

Tricky equals() in Java

Behavior of equal() in Java with different Objects

Integer class

Integer i2 = new Integer(100);
Integer i3 = 100;
System.out.println(i2.equals(i3));

public boolean equals(Object paramObject) {
            if (paramObject instanceof Integer)
                  return (this.value == ((Integer) paramObject).intValue());
            return false;
      }

All wrapper classes overriding equals() and thus checking actual value instead of addresses.

String class

 public boolean equals(Object paramObject) {
              if (this == paramObject)
                     return true;
              if (paramObject instanceof String) {
                     String str = (String) paramObject;
                     int i = this.value.length;
                     if (i == str.value.length) {
                           char[] arrayOfChar1 = this.value;
                           char[] arrayOfChar2 = str.value;
                           for (int j = 0; i-- != 0; ++j)
                                  if (arrayOfChar1[j] != arrayOfChar2[j])
                                         return false;
                           return true;
                     }
              }
              return false;
       }

Object Class

public boolean equals(Object paramObject) {
              return (this == paramObject);
       }


public class EqualsMethod {

     public static void main(String[] args) {
           Integer i1 = new Integer(200);
           Integer i2 = 200;
           Integer i3 = new Integer(200);
           System.out.println("--equals() for Integer Object--");
           // Checking address and not values
           System.out.println(i1 == i2);
           // equals() Checks values thus result is true
           System.out.println(i1.equals(i2));
           System.out.println(i1.equals(i3));

           System.out.println("--equals() for Build In Object--");

           Employeee e1 = new Employeee("Paras", "Rohtak");
           Employeee e2 = new Employeee("Paras", "Rohtak");
           System.out.println(e1.equals(e2));
           System.out.println(e1 == e2);
          
           System.out.println("--equals() for String Object--");
           String s1= new String("Paras");
           String s2= new String("Paras");
           String s3="Paras";
           // Check values and not address
           System.out.println(s1.equals(s3));
           System.out.println(s1.equals(s2));
           System.out.println(s1==s2);
     }
}

class Employeee {
     String name;
     String address;

     Employeee(String name, String address) {
           this.name = name;
           this.address = address;
     }
}



Output:
--equals() for Integer Object--
false
true
true
--equals() for Build In Object--
false
false
366712642
--equals() for String Object--
true
true
false