Showing posts with label Java Tutorials. Show all posts
Showing posts with label Java Tutorials. Show all posts

Saturday, September 24, 2016

How to solve Producer Consumer problem in Java using wait and notify method

Producer Consumer problem can be easily solved by using just wait and notify method using inter-thread communication where one thread is used to produce and another thread is used to consume. Here the wait and notify method will be used for inter-thread communication to notify other party (Producer by Consumer thread and vice-versa).

To solve this problem, I have used the ArrayList as shared object, where producer thread puts the object (Just Integer in this case) and consumer thread consumes the object (integer). Interestingly, I have used the same list object as monitor lock, thus removing the additional overhead to create shared monitor lock.


Here is the code example:


import java.util.ArrayList;

public class ProducerConsumer {

 public static void main (String[] args) {
  ArrayList<Integer> list = new ArrayList<Integer>();
  Thread t1 = new Thread(new Producer(list));
  Thread t2 = new Thread(new Consumer(list));
  t1.start();
  t2.start();
  
 }
}

class Producer implements Runnable {
 
 private ArrayList<Integer> list;
 Producer(ArrayList<Integer> list) {
  this.list = list;
 }

 @Override
 public void run() {
  int count = 1;
  while(count <= 3) {
   synchronized(list) {
    list.add(count);
    System.out.println("Produced ::"+ count);
    count++;
    try {
     list.notify();
     list.wait();
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }
  
 }
}


class Consumer implements Runnable {
 
 private ArrayList<Integer> list;
 Consumer(ArrayList<Integer> list) {
  this.list = list;
 }
 
 @Override
 public void run() {
  int count = 1;
  while(count <= 3) {
   synchronized(list) {
    while(list.size() == 0){
     try {
      list.notify();
      list.wait();
     } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
    Integer value = list.remove(0);
    System.out.println("Consumed ::"+ value);
    count++;
    try {
     list.notify();
     list.wait();
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }
 }
}

Output:

Produced ::1
Consumed ::1
Produced ::2
Consumed ::2
Produced ::3
Consumed ::3

Explanations:

In the above code example, we are starting two threads (one Producer and one Consumer). To avoid the consumer start executing and consuming first, I have put code to check if producer has already produced or not (i.e. if there is anything on list or not). This is to address race-condition between producer and consumer threads.
Here, the producer thread is putting 3 objects (Integer in the example) in the list. Please note that the call by Producer thread and Consumer thread to put objects and retrieve objects is synchronized on the same lock (array list object in this example). This way, we guarantee that either the code of producer or code of consumer is executing inside cpu and not both at the same time. We have produced three objects and consumed three synchronously i.e producer put one, consumer consumed then again producer produced another  and ...
So, when producer produced an object, it calls notify to make sure that if the consumer threads is in waiting state, it goes back to runnable state and ready to consume and the producer thread goes to wait state (and releasing the lock) and then consumer thread which has been in runnable states gets the lock (after producer releases it), consumes the object, notify the producer to produce another and same cycle repeats for the 3 times.

That's all for the solution of producer consumer problem using wait and notify method with the help of above code example. If you have any question. please feel free to ask in comment section.

Friday, March 25, 2016

Java Queue Example

What is Queue:

Queue is one of an important data structure which typically (but not necessarily) abide by rule of FIFO (First In First Out) i.e. the element which will be inserted first will be removed from the queue in that insertion order. The time complexity of queue in best case scenario should be O(1) both in case of element insertion or element removal.


Queue in Java:

In Java, Queue (java.util.Queue) is defined as an interface. It means that any java class that can be called as Queue will need to abide by contract defined in java.util.Queue interface by either implementing Queue interface or its sub-interface (BlockingQueue, BlockingDeque, Deque, TransferQueue). If you need skeleton class on top of which you can write up your own queue implementation, then there is AbstractQueue class that will come handy (as name indicates its an abstract class).


Queue Sub-interface:

There are four interface which extends Queue. These are:
    • BlockingQueue - Provide additional feature of thread blocked (go to wait state) while fetching from empty queue and while trying to insert element when the queue is full.
    • BlockingDeque - Provide additional feature of thread blocked (go to wait state) while fetching from empty queue and while trying to insert element when the deque is full.
    • Deque - Deque is double ended queue, which means the insertion and deletion of element is allowed from both end.
    • TransferQueue - The thread inserting element to TransferQueue may wait for any consuming thread to retreive the element. Useful in message passing applications.


Implementation in Java:

There are already ready-to-use Queue (Java Classes) provided in Java library. These are:
    • LinkedList - Similar to Double Linked list i.e. each element has reference to previous and next element. That is why it is preferred over ArrayList when the insertion and deletion operation is more than just reading the list. This is an important interview question on collection framework for fresher as the main difference between ArrayList and LinkedList.
    • PriorityQueue - Inserted elements are ordered as per natural ordering or as per comparator provided. This means in PriorityQueue, the elements is not required to follow FIFO model as there can be comparator which can insert element based on comparator result in between the queue itself.
    • ArrayBlockingQueue - A bounded blocking queue. Consider ArrayBlockingQueue as a fixed size array acting on FIFO model with additional feature of thread gets blocked when queue is full / empty.
    • LinkedBlockingQueue - An optionally bounded blocking queue (Blocking queue feature can be applicable only to bounded collections). Consider LinkedBlockingQueue as Linkedlist following FIFO model with its size can be limited (bounded) or unlimited (Integer.MAX_VALUE). Threads cannot be blocked in unbounded LinkedBlockingQueue during insertion, so blockingqueue feature will not be fully applicable to unbounded LinkedBlockingQueue (only in case of retrieval).
    • PriorityBlockingQueue - An unbounded Priority Queue with feature of Blocking Queue is limited to the retreival of its element (as this queue is unbounded).
    • ConcurrentLinkedQueue - An unbounded LinkedBlockingQueue with thread-safety features. This means multiple threads can insert / delete / retreive elements on ConcurrentLinkedQueue parallely. Since it is unbounded, blocking queue feature is limited to the retreival of element only (i.e. thread attempting to retreive element from empty queue will get blocked only waiting till the insertion of element).
    • ConcurrentLinkedDeque - An unbounded thread safe "double ended queue" based on linked nodes.
    • ArrayDeque - A deque with resizeable array. Since it has array implementation, its performance is better than Stack and Linkedlist. However it is not thread-safe.
    • DelayQueue - An unbounded Blocking queue (no limit on size) to which an element can only be retreived after its delay has expired. 
    • LinkedBlockingDeque - An optionally bounded blocking "double ended queue". If size is specified when creating LinkedBlockingDeque object it will belcome bounded otherwise unbounded. Thread will get blocked in LinkedBlockingDeque while retreiving an empty queue and will get blocked while adding an element to full bounded LinkedBlockingDeque. It is based on linked nodes.
    • LinkedTransferQueue - An unbounded TransferQueue based on linked nodes. The size method is not a constant time operation and may vary.
    • SynchronousQueue - It works by putting the insert operation thread to wait for remove operation by another thread.  In other words, the thread inserting element to Synchronous Queue gets blocked till another thread takes the element out and vice-versa. 
I will provide example of each type of queue in separate article and link it out with above.

Queue Behaviour / Usage :

Queue provides additional way to insert, delete and examine object. For each insert, delete and examine operation, there are corresponding 2 methods, one throws exception and other return special value in case of failure.
Besides this, any Queue will also have all the properties of Collection as Queue interface extends Collection interface


Methods of Queue Interface:

As discussed above, the queue provides 2 methods for each insert, delete and examine operation.
These are:

Insert Operation:

add(e) -> returns true when success and throws exception in case of failure.
offer(e) -> returns true when success and false in case of failure.

Remove Operation:

remove() -> removes the head element. Returns head element when success and throws exception in case of failure.
poll() -> removes the head element. Returns head element when success and returns null in case of failure.

Examine Operation:

element() -> retrieves (but do not remove) the head element. Returns element when true and throws NoSuchElementException in case of failure (i.e. when the queue is empty).
peak() -> retrieves (but do not remove) the head element. Returns element when true and null in case of failure (i.e. when the queue is empty)



Code Example:


import java.util.LinkedList;
import java.util.Queue;

public class QueueExample {

 public static void main (String[] args) {
  Queue que = new LinkedList();
  que.add("first");
  que.offer("second");
  que.offer("third");
  System.out.println("Queue Print:: " + que);
  
  String head = que.element();
  System.out.println("Head element:: " + head);
  
  String element1 = que.poll();
  System.out.println("Removed Element:: " + element1);
  
  System.out.println("Queue Print after poll:: " + que);
  String element2 = que.remove();
  System.out.println("Removed Element:: " + element2);
  
  System.out.println("Queue Print after remove:: " + que);  
 }
}


Output:
Queue Print:: [first, second, third]
Head element:: first
Removed Element:: first
Queue Print after poll:: [second, third]
Removed Element:: second
Queue Print after remove:: [third]



Conclusion:

That's all for example of Queue in Java. I will provide details of each implementing class of Queue Interface in separate post. It is important to mention that all queue methods which throws exceptions needs to be handled wisely.

Wednesday, March 9, 2016

How to create shippable desktop applications in java using Eclipse IDE

Problem Statement:
I want to create a jar which I can run standalone using Eclipse IDE

Solution:
When the code is ready and all the code is written up and the application is ready to be shipped as standalone application, following are the steps needed:

(a) First recheck whether there is no compilation error.

(b) Confirm all the dependency project and jar is in the build path

(c) Right click on java file which contains main method and click Run As -> Java Application, this will set the launch configuration (see next step)

(d) Now Right click on the project and click "Export...". It will open a Export Dialog Box

(e) On the Export Dialog, select Runnable JAR file inside java tree selection and click Next

(f) Choose from Launch configuration (it will give you the entry point i.e. java file with main method, see step (c) for that)

(g) Choose Export Destination (i.e. jar name and its path where it will be created). Make sure you provide valid path. Use "Browse.." button to choose or select.

(h) select Package required libraries into generated JAR option

(i) click Finish button.

Your jar is ready to be shipped as standalone desktop application.

Monday, February 29, 2016

Java Exchanger

Introduction to Java Exchanger

Java Exchanger class is a synchronization point where threads can swap elements. In other words, Exchanger provides two way mechanism to exchange objects between threads. So now you can give your object and take his objects between pairs. It is some sort of bidirectional form of SynchronousQueue.

It is available from Java 1.5 however it is not very much known class to many Java developer.


Benefits of Java Exchanger

Passing data between threads in java is possible through Exchanger class. It solves the purpose of the problem of bidirectional exchange of objects.


Real Time Example / Use case

In Juice Factory, the juice is first extracted from fruits and stored in a large container, which is being sent for individual Packaging. Considering the above real time example / use case, JuiceExtraction system and Packaging System are the individual independent threads which can pair to exchange the Juice Container. Here the exchange item is the container. During pairing, JuiceExtraction container will pass filled-up container and receive the empty container. 

Here is the code sample for the above real time use case:

import java.util.concurrent.Exchanger;

public class JuiceFactory {
Exchanger<JuiceFactory.Container> exchanger = new Exchanger<JuiceFactory.Container>();

class JuiceExtraction implements Runnable{
Container currentContainer;
public JuiceExtraction(Container c){
this.currentContainer = c;
}
@Override
public void run() {
try {
while(currentContainer != null) {
// Extract juice and fill inside container
int result = currentContainer.fill(20);
if(result > 0) { 
// Container capacity is full, pass this container to Packaging
// system through Exchanger.

// wait till get a free container from Packaging system
currentContainer = exchanger.exchange(currentContainer); 


}
} catch (InterruptedException e) {
e.printStackTrace();
}

}

}


class Packaging implements Runnable{
Container currentContainer;
public Packaging(Container c){
this.currentContainer = c;
}

@Override
public void run() {
try {
while(currentContainer != null) {
// Takeout juice for packaging in bottle
int result = currentContainer.takeOut(25);
if(result > 0) {
// Container is empty. Pass this empty container to Juice extraction
// system and take another full container for packaging
currentContainer = exchanger.exchange(currentContainer);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}

}

}

class Container {
int capacity = 100;
int currentFillup = 0;

public Container (int initialVolume) {
currentFillup = initialVolume;
}
public int fill(int volume) {
if(currentFillup+volume > capacity) {
volume = volume - (capacity - currentFillup);
currentFillup = capacity;
return volume;
} else {
currentFillup+=volume;
return 0;
}
}

public int takeOut(int volume) {
if(currentFillup - volume < 0) {
volume = volume - (volume - currentFillup);
currentFillup = 0;
return volume ;
} else {
currentFillup-=volume;
return 0;
}
}
}

void start() {
new Thread (new JuiceExtraction(new Container(0))).start();
new Thread (new Packaging(new Container(100))).start();
}
}



Other Ideas:
Through Exchanger, we can also address Producer Consumer Problem Statement besides the areas where we need to exchange the objects between threads

If there is an application where it is required to be both one directional exchange and bi-directional based on certain criteria, we can use Exchanger as a one directional exchange (only give and receive null) and also bi-directional (both give and take).



Java SynchronousQueue (Synchronous Queue) Example

Java SynchronousQueue class is the only collection object which does not have any internal memory capacity. That's the beauty of this collection class and thus many fellow use to ask this in interview question about which Java collection class has no memory capacity? (Answer)

Now you might be wondering if it has no memory capacity, not even of one, then how come this collection framework is even working and how can anyone use it?

First of all, Synchronous Queue comes under the class of Blocking Queue i.e. it has all the features of Blocking Queue
Hence it works by putting the insert operation thread to wait for remove operation by another thread. In other words, the thread inserting element to Synchronous Queue gets blocked till another thread takes the element out and vice-versa. That means any thread tries to take out the element will get blocked if there is no another thread to put the element into the queue. So the thread which tries to put the element (and gets blocked until there is no taker) keeps hold of the element on its behalf and thus the queue size is always zero (no memory capacity of its own).

Real Time Example:
The best way to understand SynchronousQueue  is the ping-pong game, where a person passes the ball to another. Consider there are many persons and many balls for this ping-pong game. So here each person holding the ball is passing it to another person and that another person is passing to someone else and it goes on. 
In the above example, each person is a separate thread and ball is an element and it passes via Synchronous Queue. It is quite worthy to note that while Person A is passing the ball to Person B, it doesnot put the ball into any basket (Synchronous queue here) but passes directly to person B and thus the queue doesn't need to hold that ball element. So with this way N persons holding N balls blocks until another N another persons receives it.

How SynchronousQueue works internally:

When a thread put the element on Synchronous Queue, internally that thread goes to wait state on SynchronousQueue Object and when another thread take the element from the queue, it internally calls notify to SynchronousQueue Object leading to one waiting thread thread to wake up. You can also think Synchronous Queue as advanced way for Object wait() and notify() method. SynchronousQueue Object smartly uses Object's monitor lock feature to achieve this.

Thursday, February 18, 2016

Java Equals Hashcode Contract Example

This the one of the most common question we used to face during Core Java interview, however its understanding is bit tricky. I will rather take unique approach to make the understanding simple.

So, what is the contract between hashcode and equals to be used as a key to HashMap / HashSet?

Java specification says that if you want to use any object as key to a hashmap or hashset or any other hashing, the contract is that
If two objects are equal according to the equals method, then its hashCode method on each of the two objects must return the same integer result.

Why so?

To understand why this contract even come into picture, we need to understand how hashmap works. Usually in best possible scenario, the time complexity to retrieve an object from hashmap is o(1). In other words, if you ask to retrieve an object by providing key from a map of millions, it just know where exactly it is and goes directly to that object and fetch it without iterating other objects. Thats the beauty of hashing technique.

Hashing Technique:

To understand hashing technique in simple terms, consider you have written a letter to me to be delivered.
Does the postman passes goes to each person and ask his name to find me?
Definitely not. He sends your post to the pincode and then it searches among the pincode. Since in best possible scenario, there is only one person per pincode, the letter reaches to me directly. This the way hashing technique works.
When you store an object to an hashmap, its stores on the key hashcode (also known as bucket). So, while retrieving in one shot, it requires the key hashcode again and thats why it is required to have same hashcode integer result every time. If it is going to give different hashcode, HashMap stores element on different code/bucket and trying to retrieve from different code/bucket, hence unable to retrieve object even-if it is present in hashmap on different bucket / hashcode / pincode.

Java Interview Questions on Atomic variables

Here are the list of 5 good questions on Volatile and Synchronized keywords in Java:

1. What is Atomic variables and its significance:

Atomic variables performs atomic operation on its object. In other words, it operation will happen completely or will not happen at all, and no one can interrupt its operation in between. With its introduction in Java 1.5, it is being widely used in multi-thread environment without any synchronization.

2. Is Atomic variable more faster or variable through synchronized code?

For read access, it does not matter whether it is atomic or non-atomic, synchronized or non-synchronized. For write access, atomic variable does not require lock to write because all update to variable happens atomic (either happened or not happened completely) For eg: suppose you want to do i++ in a multi-threaded application and multiple threads can call this, you need to synchronized i++ call (as it is set to 3 registry levels call and you know it can be context switch at any point of registry level calls even in between) to avoid dirty reads and inconsistent write. Atomic variable has just 1 registry level calls.

3. What is the disadvantage of Atomic variables as compared to its primitive type?

All Objects in java requires more care by the programmer to avoid memory consistency errors, doesnt matter whether it is Atomic or not. While the siblings of Atomic variable can be primitive and not object, it doesn't falls into object category and hence not required to take care of memory consistency error The reason why every object requires to avoid memory consistency errors in multi-threaded application is because each thread stack caches the copy of object locally on thread stack (Runtime optimization) might result into not in sync with actual copy of heap if it gets modified by another thread (even in the same code but different thread stack). One solution to avoid is to use volatile for that object which can be changed by another thread frequently. Also the local copy tries to in sync with heap copy very fast but problem occurs if your thread access it more faster than sync happens.

4. How Atomic variables are implemented internally or how atomic variables achieves atomicity?

With the introduction of additional register being added to cpu, atomic variables harness it to achieve atomicity. Since its just 1 cpu register call, it cannot be interrupted in between.

5. What are the atomic variable classes in java?

There are only two classes: AtomicInteger and AtomicLong. There is no atomic level classes for other primitives like double, float etc.

Difference between String, String Buffer and String Builder

In Java, these are the difference between String, String Builder and String Buffer:

String String Buffer String Builder
Immutable (cannot be changed after creation) Mutable (can be changed after creation) Mutable (can be changed after creation)
Thread Safe (Can be used across threads) Thread Safe (Can be used across threads) Not thread safe
Performance is good Performance is slow due to synchronized overhead Performance is good
'+' operation can be used in String to add two strings '+' operation is not allowed '+' operation is not allowed
Stored in constant String pool Stored in Heap area of memory Stored in Heap area of memory


Sunday, February 14, 2016

Java Timer Example

Java Timer Example:

Think of a scenario where I want my code to execute at a particular time in my application or at sometime later from the current time. In other words, I want to schedule my task at the definite time. How can this be possible using Java Programming language?

Tutorial:

Java Timer class (java.util.Timer) allows an application to schedule the task on a separate background thread. Please note that by default the associated thread is a non-daemon thread i.e. application does not terminate pending timer thread to complete execution.However, you can change the associated thread to Timer Class as Daemon Thread during creation of Timer Object. (Learn more about Daemon Thread in java)

Timer Task:

Timer class needs Timer Task (java.util.TimerTask) (Runnable Object) to execute the task. This is the class where the actual logic implementation resides inside run method. Timer when scheduled, picks up Timer Task and executes (once or repetitive as the case may be).

How to schedule Task:

Timer class provides various ways to schedule the task based on number of execution and rate of execution. Here are the list:

Method Signature

Purpose

schedule (TimerTask task, Date time)  Schedule task at specified Date time. It will be executed only once on the time specified
schedule (TimerTask task, Date firstTime, long period)  Schedule task at specified Date time. It will start executing from the specified date time and then repeat after the period specified henceforth
schedule (TimerTask task, long delay) Schedule task after delay time. It will be executed only once on the delay time specified from the current time
schedule (TimerTask task, long delay, long period) Schedule task after delay time with fixed delay period time unit execution thereafter. 
scheduleAtFixedRate (TimerTask task, Date firstTime, long period) Schedule task at specified Date time with fixed rate execution. It will start executing from the specified date time and then repeat after the period specified henceforth. If the task couldn't start at the specified time, the next task will get triggered before the period time to adjust the fixed rate. 
scheduleAtFixedRate (TimerTask task, long delay, long period Schedule task after delay time with fixed rate execution. It will start executing from the specified date time and then repeat after the period specified henceforth. If the task couldn't start at the specified time, the next task will get triggered before the period time to adjust the fixed rate. 


How Java Timer works internally:

Internally Timer uses binary heap data structure to store Timer tasks. The constructor to create Timer object also creates Timer Thread with it and schedule method put the task on binary heap. It works on Object.wait() call to maintain Thread wait and notify.
Timer class is also thread-safe so multiple threads can simultaneously use it.

Java Timer Code Example :

import java.util.Timer;
import java.util.TimerTask;
public class JavaTimer {
  public static void main(String[] args){
  Timer timer = new Timer();
  TimerTask task = new TimerTask() {
      @Override
   public void run() {
    System.out.println("Inside Timer Task" + System.currentTimeMillis());
       }
  };
  System.out.println("Current time" + System.currentTimeMillis());
  timer.schedule(task, 10000,1000);
  System.out.println("Current time" + System.currentTimeMillis());
   }
}

Output :

Current time1455469505220
Current time1455469505221
Inside Timer Task1455469515222
Inside Timer Task1455469516222
Inside Timer Task1455469517222
Inside Timer Task1455469518222
Inside Timer Task1455469519222
Inside Timer Task1455469520222
Inside Timer Task1455469521222
Inside Timer Task1455469522222
Inside Timer Task1455469523222
Inside Timer Task1455469524222
Inside Timer Task1455469525222
Inside Timer Task1455469526222
Inside Timer Task1455469527222
Inside Timer Task1455469528223
Inside Timer Task1455469529223 and it goes on

Analysis :

The call to timer.schedule(task, 10000,1000) is going to schedule the task which is going to execute for first time (on another thread) after 10 second from this call. After that it will call again after delay of 10 seconds. It is important to mention here that if the task cannot be started after 10 seconds, next task call will not get pre-pond. So here the delay time between two consecutive task is fixed.

How to cancel Timer Thread:

To cancel and discard all scheduled task from the queue, cancel() method needs to be called. If there is any on-going execution, it will not interrupt in between. Rather it cancels all other scheduled task from the queue and after completion of on-going task(if any), Timer thread exits gracefully.

How to cancel already running Task:

To cancel already running task, you need to identify check points where you need to cancel the task. Take AtomicInteger as signal to cancel task and change its value inside cancel() method and when cancel signal comes then inside your task there are various check points which will check the value  and exit the task (Please remember to do cleanup/rollback as needed before existing the task thread).

Wednesday, February 10, 2016

Daemon Thread in java

Introduction:

In Java, Daemon Threads are one of the types of thread which does not prevent Java Virtual Machine (JVM) from exiting.
The main purpose of daemon thread is to execute background task especially in case of some routine periodic task or work. With JVM exits, daemon thread also dies.

How to create a Daemon Thread in Java:

By setting a thread.setDaemon(true), a thread becomes a daemon thread. However, you can only set this value before the thread start.

Code Example:


public class DaemonThread {

public static void main(String[] args) {
System.out.println("Entering Main Thread");
Thread t = new Thread(new Runnable(){
@Override
public void run() {
for(int i=0; i<5; i++) {
System.out.println("Executing Daemon Thread");
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.setDaemon(true); // Thread becomes daemon thread here
t.start();
System.out.println("Exiting Main Thread");
}
}

Here is the sample output:

Output1:
Entering Main Thread
Exiting Main Thread

Output2:
Entering Main Thread
Exiting Main Thread
Executing Daemon Thread
Executing Daemon Thread

Explanation

In the above code example, main thread is spawning a daemon thread, Here main thread is the only non-deamon thread. As soon as the main thread execution completes, JVM exits and daemon thread dies alongwith.

The above code example and output illustrates the following:
  • JVM doesn't wait for the daemon thread to complete its task
  • Daemon thread dies as soon as JVM exits

Finding if the thread is daemon or not:

To know if a thread is daemon or not, you can check with Thread.isDeamon(). If returns true, the thread is daemon.

Thursday, January 28, 2016

Java Singleton Design Pattern: Double check lock

Java Singleton Design Pattern tells us to have a single copy of Java Object in memory throughout its execution life time.

In Java, it can be achieved by various ways but in Multi-threaded system, one of the beautiful ways to achieve this by applying double check locking. This will ensure faster and efficient way in multi-threaded environment.

Locking via synchronizing method:
Yes Singleton Design pattern in Java can also be achieved by synchronizing method but its inefficient.

Here is an example:

public class Singleton {
private static Singleton pattern = null;

public static synchronized Singleton getInstance() {
if(pattern == null) {
pattern = new Singleton();
}
return pattern;
}
}

Consider there are many threads trying to call getInstance method. Only one can acquire lock and rest will have to wait till the first one releases it (even for fetching this object). This makes it too inefficient in Multi-threaded environment.

Double Check Locking:
Consider below code snippet example for double Null check and locking for Singleton Design Pattern.

public class Singleton {
private static Singleton design = null;

public static Singleton getInstance() {
if(design == null) {
synchronized(Singleton.class) {
if(design == null) {
design = new Singleton();
}
}
}
return design;
}
}

The above code is most optimized for Multi-threaded system. The first null check is essential after Singleton object has already been created by first thread entering the synchronized block and hence getting the instance of this object does not have to deal with acquiring lock by each thread.

Why second null check :
Ever wondered why you need to check object reference null again after acquire lock (as it has already been checked before acquiring lock). Consider the case where two or more threads passes first null check barrier and only one thread enters the lock, while making other waiting for that lock. When the first thread releases the lock after giving call to object creation, the rest others thread will not be aware of object creation and will go and acquire lock and create object (as it has already executed first null check when there is no object created). This will result in creating more than one IAmSingle object breaking the purpose of singleton design pattern.

Everything fine with above code?
So, does the above code is full proof of creating Single Object in Multi-threaded environment. Well actually its not. Any guess?

Well the answer lies hidden in way Java Virtual Machine creates object in heap memory area. To achieve optimization, JVM give instruction to create object and the code flows continues. It might happen (very rarely) while object is in process of being created, the next thread acquires lock and have passed call to second null check!!!!!! resulting in two objects being created!!!

Fix / Solution: 
For Java 5 and later, making the reference variable volatile will fix the above problem. This has been possible due to change in the way volatile works in Java 5. With Java 5, it is guaranteed that the write to a volatile field happens-before every subsequent read of that same volatile and hence no next read will get half baked / null singleton object (https://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html)

Volatile vs Synchronized performance overhead:
Now since volatile is required to work multithreaded singleton design pattern, there has been a long debate that there is no performance advantage if we use volatile over synchronized call. Please note that volatile is cheap as compared to using synchronized overhead.