In the previous post, Java Design Pattern which talks list of design patterns available in java
In this post, we will learn what is Singleton design pattern and it’s different implementations. Singleton design patterns help us to create one and only one object of a class within the JVM.
- Singleton Eager initialization
- Singleton Lazy Initialization
- Thread Safe Singleton
- Static block initialization
- Bill Pugh Singleton Implementation
- Using Reflection to destroy Singleton Pattern
- Serialization and Singleton
- Enum Singleton
Example within JDK:
A. Singleton Eager initialization
Singleton Class using Eager initialization
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package com.kkjavatutorials.singleton; /** * Singleton Class using Eager initialization * @author KK JavaTutorials */ public class Singleton { //Eager initialization private static final Singleton INSTANCE = new Singleton(); /* * private constructor so that * preventing instance creation from other class */ private Singleton() { } /** * This method has global access to return * Single instance within JVM * @return Singleton Instance */ public static Singleton getInstance() { return INSTANCE; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package com.kkjavatutorials.client; import com.kkjavatutorials.singleton.Singleton; /** * Client Program getting singleton instance * of Singleton class * @author KK JavaTutorials */ public class ClientTest { public static void main(String[] args) { /** * Calling getInstance() method many times * returns same hashcode that proves that * Singleton class creates only one instance */ Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = Singleton.getInstance(); System.out.println(singleton1.hashCode()); System.out.println(singleton2.hashCode()); } } |
Output of ClientTest.java
2018699554
2018699554
NOTE: Calling getInstance() method many times returns the same hashcode that proves that the Singleton class creates only one instance within the JVM
B. Singleton Lazy Initialization
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package com.kkjavatutorials.singleton; /** * Singleton Class using Lazy initialization * @author KK JavaTutorials */ public class Singleton { private static Singleton INSTANCE = null; /* * private constructor so that * preventing instance creation from other class */ private Singleton() { } /** * This method has global access to return * Single instance within JVM * @return Singleton Instance */ public static Singleton getInstance() { //If Instance is null then only instantiate if (INSTANCE == null) { INSTANCE = new Singleton(); } return INSTANCE; } } |
Client Program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package com.kkjavatutorials.client; import com.kkjavatutorials.singleton.Singleton; /** * Client Program getting singleton instance * of Singleton class * @author KK JavaTutorials */ public class ClientTest { public static void main(String[] args) { /** * Calling getInstance() method many times * returns same hashcode that proves that * Singleton class creates only one instance */ Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = Singleton.getInstance(); System.out.println(singleton1.hashCode()); System.out.println(singleton2.hashCode()); } } |
Output of ClientTest.java
2018699554
2018699554
NOTE: Calling getInstance() method many times returns the same hashcode that proves that the Singleton class creates only one instance within the JVM
C. Thread Safe Singleton
Singleton.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package com.kkjavatutorials.singleton; public class Singleton { private static Singleton INSTANCE = null; private Singleton() { } public static Singleton getInstance() { if (INSTANCE == null) { synchronized (Singleton.class) { if (INSTANCE == null) { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } INSTANCE = new Singleton(); } } } return INSTANCE; } } |
MyThread.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.kkjavatutorials.client; import com.kkjavatutorials.singleton.Singleton; public class MyThread implements Runnable { @Override public void run() { Singleton singleton = Singleton.getInstance(); System.out.println(Thread.currentThread().getName()+" "+singleton.hashCode()); } } |
ClientTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
package com.kkjavatutorials.client; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ClientTest { public static void main(String[] args) { ExecutorService executorService = null; MyThread myThread = new MyThread(); try { executorService = Executors.newFixedThreadPool(5); executorService.execute(myThread); executorService.execute(myThread); executorService.execute(myThread); executorService.execute(myThread); executorService.execute(myThread); executorService.execute(myThread); } catch (Exception e) { e.printStackTrace(); }finally { if(executorService != null) executorService.shutdown(); } } } |
Output of this client program:
pool-1-thread-1 2047457294
pool-1-thread-4 2047457294
pool-1-thread-2 2047457294
pool-1-thread-3 2047457294
pool-1-thread-5 2047457294
pool-1-thread-1 2047457294
NOTE: Calling getInstance() method many times by different threads returns the same hashcode that proves that the Singleton class creates only one instance within the JVM
D. Static block initialization
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package com.kkjavatutorials.singleton; /** * Singleton Class using Static Block initialization * @author KK JavaTutorials */ public class Singleton { private static Singleton INSTANCE = null; /* * private constructor so that * preventing instance creation from other class */ private Singleton() { } static { try { if(INSTANCE == null) { INSTANCE = new Singleton(); } } catch (Exception e) { e.printStackTrace(); } } /** * This method has global access to return * Single instance within JVM * @return Singleton Instance */ public static Singleton getInstance() { return INSTANCE; } } |
Client Program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package com.kkjavatutorials.client; import com.kkjavatutorials.singleton.Singleton; /** * Client Program getting singleton instance * of Singleton class * @author KK JavaTutorials */ public class ClientTest { public static void main(String[] args) { /** * Calling getInstance() method many times * returns same hashcode that proves that * Singleton class creates only one instance */ Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = Singleton.getInstance(); System.out.println(singleton1.hashCode()); System.out.println(singleton2.hashCode()); } } |
Output of this program:
2018699554
2018699554
NOTE: Calling getInstance() method many times returns the same hashcode that proves that the Singleton class creates only one instance within the JVM
E.Bill Pugh Singleton Implementation
Singleton.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.kkjavatutorials.singleton; public class Singleton { private Singleton() { } private static class SingletonHolder{ private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } } |
ClientTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.kkjavatutorials.client; import com.kkjavatutorials.singleton.Singleton; public class ClientTest { public static void main(String[] args) { Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = Singleton.getInstance(); System.out.println(singleton1.hashCode()); System.out.println(singleton2.hashCode()); } } |
Output of this client program:
2018699554
2018699554
NOTE: Calling getInstance() method many times returns the same hashcode that proves that the Singleton class creates only one instance within the JVM
F.Using Reflection to destroy Singleton Pattern
Singleton.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.kkjavatutorials.singleton; public class Singleton { private static Singleton INSTANCE = null; private Singleton() { } public static Singleton getInstance() { if (INSTANCE == null) { INSTANCE = new Singleton(); } return INSTANCE; } } |
ClientTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.kkjavatutorials.client; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import com.kkjavatutorials.singleton.Singleton; public class ClientTest { public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = null; Constructor<?>[] constructors = Singleton.class.getDeclaredConstructors(); for (Constructor<?> constructor : constructors) { constructor.setAccessible(true); Object object = constructor.newInstance(); singleton2 = (Singleton)object; break; } System.out.println(singleton1.hashCode()); System.out.println(singleton2.hashCode()); } } |
Output of this client program:
2018699554
1311053135
NOTE: Calling getInstance() method many times returns different hashcodes that proves that the Singleton is broken by using reflection API.
G.Serialization and Singleton
Singleton.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
package com.kkjavatutorials.singleton; import java.io.Serializable; /** * Singleton Class implements Serializable * @author KK JavaTutorials */ public class Singleton implements Serializable{ private static final long serialVersionUID = 1808144385520819134L; private static Singleton INSTANCE = null; /* * private constructor so that * preventing instance creation from other class */ private Singleton() { } /** * This method has global access to return * Single instance within JVM * @return Singleton Instance */ public static Singleton getInstance() { if (INSTANCE == null) { INSTANCE = new Singleton(); } return INSTANCE; } /** * This method protecting to break singleton * by using Serialization process * @return return singleton instance */ public Object readResolve() { return getInstance(); } } |
ClientTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
package com.kkjavatutorials.client; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import com.kkjavatutorials.singleton.Singleton; /** * Client Program which is trying * to break singleton using Serialization * process * @author KK JavaTutorials */ public class ClientTest { public static void main(String[] args) throws IOException { ObjectOutput objectOutput = null; Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = null; try { objectOutput = new ObjectOutputStream(new FileOutputStream("singleton.ser")); objectOutput.writeObject(singleton1); objectOutput.flush(); } catch (Exception e) { e.printStackTrace(); }finally { if(objectOutput != null) objectOutput.close(); } ObjectInput objectInput = null; try { objectInput = new ObjectInputStream(new FileInputStream("singleton.ser")); Object readObject = objectInput.readObject(); singleton2 = (Singleton)readObject; } catch (Exception e) { e.printStackTrace(); }finally { if(objectInput != null) objectInput.close(); } /** * hascode of original singleton * object(singleton1) and serialized * object(singleton2) are same * so singleton has not broken. */ System.out.println(singleton1.hashCode()); System.out.println(singleton2.hashCode()); } } |
Output of this client program:
1028566121
1028566121
NOTE: Calling getInstance() method many times returns the same hashcode that proves that the Singleton class creates only one instance within the JVM
H.Enum Singleton
Singleton.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.kkjavatutorials.singleton; /** * Singleton Class using Enum * @author KK JavaTutorials */ public enum Singleton { /** * This Singleton can be access globally */ GETINSTANCE; public String welcome() { return "Singleton!!"; } } |
ClientTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package com.kkjavatutorials.client; import com.kkjavatutorials.singleton.Singleton; /** * Client Program getting singleton instance * of Singleton class * @author KK JavaTutorials */ public class ClientTest { public static void main(String[] args) { /** * Calling getInstance() method many times * returns same hashcode that proves that * Singleton class creates only one instance */ Singleton singleton1 = Singleton.GETINSTANCE; Singleton singleton2 = Singleton.GETINSTANCE; System.out.println(singleton1.hashCode()); System.out.println(singleton2.hashCode()); String welcome = singleton1.welcome(); System.out.println(welcome); } } |
Output of this client program:
2018699554
2018699554
Singleton!!
NOTE: Calling getInstance() method many times returns the same hashcode that proves that the Singleton class creates only one instance within the JVM
You May Also Like:
Prototype Pattern
Factory Pattern
Abstract Factory Pattern
Builder Pattern
That’s all about Singleton Design Pattern in java
If you have any feedback or suggestion please feel free to drop in below comment box.