MenuPage

Monday, August 20, 2018

Singleton Design pattern

The Singleton pattern is deceptively simple, even and especially for Java developers, but it presents a number of pitfalls for the unwary Java developer which make it hard to implement properly. In this article, I’ll talk about several ways to implement the Singleton pattern in Java, and leave it to you to decide which one is best suited for your circumstance depending on your requirement.
With the Singleton design pattern you can:
  • Ensure that only one instance of a class is created
  • Provide a global point of access to the object
  • Allow multiple instances in the future without affecting a singleton class’s clients

The classic Singleton pattern1

In Design Patterns: Elements of Reusable Object-Oriented Software, the GoF describe the Singleton pattern like this:

Ensure a class has only one instance, and provide a global point of access to it.
public class ClassicSingleton {
2     private static ClassicSingleton instance = null;
3 
4     private ClassicSingleton() {
5         // Exists only to defeat instantiation.
6     }
7 
8     public static ClassicSingleton getInstance() {
9         if (instance == null) {
10             instance = new ClassicSingleton();
11         }
12         return instance;
13     }
14 }


Above code is easy to understand, the ClassicSingleton hold a static reference to the single instance and returns that reference from the static getInstance() method.
There are several interesting points concerning the ClassicSingleton class.
 1 > ClassicSingleton employs a technique known as lazy instantiation to create the singleton; as a result, the singleton instance is not created until the getInstance() method is called for the first time. This technique ensures that singleton instances are created only when needed.

2> It’s possible to have multiple singleton instances if classes loaded by different Classloaders access a singleton. That scenario is not so far-fetched; for example, some servlet containers use distinct Classloaders for each servlet, so if two servlets access a singleton, they will each have their own instance.

3> If ClassicSingleton implements the java.io.Serializableinterface, the class’s instances can be serialized and deserialized. However, if you serialize a singleton object and subsequently deserialize that object more than once, you will have multiple singleton instances.

4> ClassicSingleton class is not thread-safe. If two threads—we’ll call them Thread 1 and Thread 2—call ClassicSingleton.getInstance() at the same time, two ClassicSingleton instances can be created if Thread 1 is preempted just after it enters the if block and control is subsequently given to Thread 2.

5> A privileged client can invoke the private constructor reflectively with the aid of the AccessibleObject.setAccessible method. If you need to defend against this attack, modify the constructor to make it throw an exception if it’s asked to create a second instance.
As you can see from the preceding discussion, although the Singleton pattern is one of the simplest design patterns, implementing it in Java is anything but simple. The rest of this article addresses Java-specific considerations for the Singleton pattern.

Synchronization for multithreading considerations

Making Singleton thread-safe is easy-just synchronize the getInstance() method:



1 public class Singleton {
2     private static Singleton instance = null;
3 
4     private Singleton() {
5         // Exists only to defeat instantiation.
6     }
7 
8     public synchronized static Singleton getInstance() {
9         if (instance == null) {
10             instance = new Singleton();
11         }
12         return instance;
13     } 


However, the astute reader may realize that the getInstance() method only needs to be synchronized the first time it is called. Because synchronization is very expensive performance-wise, perhaps we can introduce a performance enhancement that only synchronizes the singleton assignment in getInstance().

A performance enhancement

In search of a performance enhancement, you might choose to rewrite the getInstance()method like this:


1 // CAUTION, BUGS AHEAD
2 public static Singleton getInstance() {
3    if(singleton == null) {
4       synchronized(Singleton.class) { 
5          singleton = new Singleton();
6       }
7    }
8    return singleton; 

Instead of synchronizing the entire method, the preceding code fragment only synchronizes the critical code. However, the preceding code fragment is not thread-safe. Consider the following scenario: Thread 1 enters the synchronized block, and, before it can assign the singleton member variable, the thread is preempted. Subsequently, another thread can enter the if block. The second thread will wait for the first thread to finish, but we will still wind up with two distinct singleton instances. Is there a way to fix this problem? Read on.

Double-checked locking

Double-checked locking is a technique that, at first glance, appears to make lazy instantiation thread-safe. That technique is illustrated in the following code fragment:

1 // CAUTION, BUGS AHEAD
2 public static Singleton getInstance() {
3   if(singleton == null) {
4      synchronized(Singleton.class) {
5        if(singleton == null) {
6          singleton = new Singleton();
7        }
8     }
9   }
10   return singleton; 
11

What happens if two threads simultaneously access getInstance()? Imagine Thread 1 enters the synchronized block and is preempted. Subsequently, a second thread enters the if block. When Thread 1 exits the synchronized block, Thread 2 makes a second check to see if the singleton instance is still null. Since Thread 1 set the singleton member variable, Thread 2’s second check will fail, and a second singleton will not be created. Or so it seems.
Unfortunately, double-checked locking is not guaranteed to work because the compiler is free to assign a value to the singleton member variable before the singleton’s constructor is called. If that happens, Thread 1 can be preempted after the singleton reference has been assigned, but before the singleton is initialized, so Thread 2 can return a reference to an uninitialized singleton instance.
Since double-checked locking is not guaranteed to work, you must synchronize the entire getInstance() method. However, another alternative is simple, fast, and thread-safe.

An alternative thread-safe singleton implementation


1 public class Singleton {
2    public final static Singleton INSTANCE = new Singleton();
3    private Singleton() {
4        // Exists only to defeat instantiation.
5    }
6 }
The preceding singleton implementation is thread-safe because static member variables created when declared are guaranteed to be created the first time they are accessed. You get a thread-safe implementation that automatically employs lazy instantiation, until the class file get loaded into memory, their is no instance instanciated at all.


Of course, like nearly everything else, the preceding singleton is a compromise; if you use that implementation, you can’t change your mind and allow multiple singleton instances later on. With a more conservative singleton implementation, instances are obtained through a getInstance() method, and you can change those methods to return a unique instance or one of hundreds. You can’t do the same with a public static member variable.
1 public class Singleton {
2    private final static Singleton INSTANCE = new Singleton();
3    private Singleton() {
4        // Exists only to defeat instantiation.
5    }
6 
7    public static Singleton getInstance() {
8        return INSTANCE;
9    }
10 }

Leveraging volatile to change Java Memory Model

We can recheck the instance again in synchronized block to ensure that only one instance of the Singleton object be instantiated, shown as below code:
1 public class LazySingleton {
2     private static volatile LazySingleton instance;
3 
4     // private constructor
5     private LazySingleton() {
6     }
7 
8     public static LazySingleton getInstance() {
9         if (instance == null) {
10             synchronized (LazySingleton.class) {
11                 // Double check
12                 if (instance == null) {
13                     instance = new LazySingleton();
14                 }
15             }
16         }
17         return instance;
18     }
19 }
Please ensure to use volatile keyword with instance variable otherwise you can run into out of order write error scenario, where reference of instance is returned before actually the object is constructed i.e. JVM has only allocated the memory and constructor code is still not executed. In this case, your other thread, which refer to uninitialized object may throw null pointer exception and can even crash the whole application.
Although above code is the correct way to implement Singleton pattern, this is not recommended since it introduce extra complexity of code, which may introduce subtle bugs.

Classloaders

Because multiple classloaders are commonly used in many situations—including servlet containers—you can wind up with multiple singleton instances no matter how carefully you’ve implemented your singleton classes. If you want to make sure the same classloader loads your singletons, you must specify the classloader yourself; for example:
1 private static Class getClass(String classname) throws ClassNotFoundException {
2     ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
3     if(classLoader == null)
4         classLoader = Singleton.class.getClassLoader();
5         return (classLoader.loadClass(classname));
6     }
7 }
The preceding method tries to associate the classloader with the current thread; if that classloader is null, the method uses the same classloader that loaded a singleton base class. The preceding method can be used instead of Class.forName().

Serialization2

If you serialize a singleton and then deserialize it twice, you will have two instances of your singleton, unless you implement the readResolve() method, like this:
1 public class Singleton implements java.io.Serializable {
2     private static final long serialVersionUID = 1L;
3     public static Singleton INSTANCE = new Singleton();
4 
5     private Singleton() {
6         // Exists only to thwart instantiation.
7     }
8 
9     private Object readResolve() {
10         return INSTANCE;
11     }
12 }
The previous singleton implementation returns the lone singleton instance from the readResolve() method; therefore, whenever the Singleton class is deserialized, it will return the same singleton instance. Don’t forget to add serial version id in this case, or you will get an exception during de-serialise process.

Bill Pugh solution3

Bill Pugh was main force behind java memory model changes. His principle “Initialization-on-demand holder idiom” also uses static block but in different way. It suggest to use static inner class:
1 public class BillPughSingleton {
2     private BillPughSingleton() {
3     }
4 
5     private static class LazyHolder {
6         private static final BillPughSingleton INSTANCE = new BillPughSingleton();
7     }
8 
9     public static BillPughSingleton getInstance() {
10         return LazyHolder.INSTANCE;
11     }
12 }
As you can see, until we need an instance, the LazyHolder class will not be initialized until required and you can still use other static members of BillPughSingleton class. This is the solution, i will recommend to use. I also use it in my all projects.

Using Enum

As of release 1.5, there is a another approach to implementing singletons. which provide implicit support for thread safety and only one instance is guaranteed. This is also a good way to have singleton with minimum effort. Simply make an enum type with one element:
1 // Enum singleton - the preferred approach
2 public enum LazyEnumSingleton {
3     INSTANCE;
4     public void otherMethods() { System.out.println("Other methods go"); }
5 }
This approach is functionally equivalent to the public field approach, except that it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton. JVM does the lazy-loading in a thread-safe manner. That’s why using this kind of lazy class loading is the preferred method—the JVM handles all the synchronization. We can see that with below little example code, try run it your self:
1 public class LazyEnumSingletonExample {
2     public static void main(String[] args) throws InterruptedException {
3         System.out.println("Accessing enum for the first time.");
4         LazyEnumSingleton lazy = LazyEnumSingleton.INSTANCE;
5         System.out.println("Done.");
6     }
7 }
8 
9 enum LazyEnumSingleton {
10     INSTANCE;
11 
12     static {
13         System.out.println("Initialize in process...");
14     }
15 }
Output of the code:
Accessing enum for the first time.
Initialize in process...
Done.
In Java, enum can hold state, which makes the single-element enum type the perfect condidate for Singleton pattern, see below code:
1 enum LazyEnumSingletonWithState {
2     INSTANCE("State") {
3 
4         @Override
5         public String toOverwrittenOps(String str) {
6             return str + this.state;
7         }
8     };
9 
10     private String state;
11 
12     private LazyEnumSingletonWithState(String state) {
13         this.state = state;
14     }
15 
16     public String otherOps(String arg) {
17         return arg + state;
18     }
19 
20     @Override
21     public String toString() {
22         return this.state;
23     }
24 
25     public abstract String toOverwrittenOps(String str);
26 }

Preventing privileged clients

As we mentioned before, single pattern can be broken with reflection, as below code shown:
1 public static void main(String[] args) throws Exception {
2     Singleton s1 = Singleton.getInstance();
3     Class clazz = Singleton.class;
4     Constructor cons = clazz.getDeclaredConstructor();
5     cons.setAccessible(true);
6     // Another instance can be instantiated now.
7     Singleton s2 = (Singleton) cons.newInstance();
8 }
It’s easy to get over this issue:
1 public class PrivilegedSingleton {
2     private static final PrivilegedSingleton INSTANCE = new PrivilegedSingleton();
3 
4     private PrivilegedSingleton() {
5 
6         // Check if we already have an instance
7         if (INSTANCE != null) {
8             throw new IllegalStateException("Singleton instance already created.");
9         }
10     }
11 
12     public static PrivilegedSingleton getInstance() {
13         return INSTANCE;
14     }
15 }
Sometimes, your IDE may remind you that the INSTANCE variable will never be null, don’t rely on that, IDE can make mistake too.



PS. copied from http://codethoughts.info/java/2014/04/07/singleton-pattern-in-java/ 

test

 import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorServi...