Singleton
It ensures only one instance for a class. More detail, it involves one class which is responsible to instantiate itself, to make sure it creates only one instance and, in the same time, it provides a global point of access to that instance.
Different implementations
There are different implementations for singleton to solve different problems. They have some common points
Constructor must be private. To ensure that only itself could instantiates itself :P A static method which should be a global point of access to get the instance
Basic
The following is the simplest way:
It ensures that only creates a Singleton object. Its constructor is private, getInstance ()
method creates only one object. But it is only suitable for single-threaded programs.
So for multi-thread, ‘synchronized’ key word must be added on getInstance()
. If no this key word, getInstance()
may return two different instances.
Now let’s suppose two threads concurrently call the getInstance()
method in the following order:
- Thread 1 calls
getInstance()
method and finds instance at // 1 is null. - Thread 1 enters
if
block, but in the implementation of the code line // 2 Thread 2 is preempted. - Thread 2 calls
getInstance()
method and finds instance at // 1 is null. - Thread 2 enters
if
block and creates a new Singleton object. - Thread 2 returns reference of instance at // 3.
- Thread 2 is preempted by Thread 1.
- Thread 1 starts where it left off and executes // 2, which lead to creation of another instance.
- Thread 1 returns reference of another instance at // 3.
So getInstance()
method creates two different instances. By synchronizing the ‘getInstance()’ method so that in the mean time, only one thread is allowed to execute code. Let’s see the next implementation.
Thread safe
Now with synchronized
key word for thread safety:
But we should only use this way when getInstance()
is not invoked too many times. Because synchronized
consumes a lot of resources.
Eager initialization
It will create an instance when load a class but before it is used by any thread. So it means, no need to synchronize the getInstance()
method, meaning all threads will see the same instance and no (expensive) locking is required. But this implementation will always creates an instance. So it is suggested to use when you are 100% sure an instance will be needed. If not, waste resource for sure.
You could also add
final
keyword on instance which means that the instance cannot be redefined, ensuring that one and only one instance ever exists.
Double-checked locking
Let’s see firstly:
I think this is reasonable, because we only need to do synchronized at // 1. But it has the same thread problem when two threads concurrently call the getInstance()
method. They do the null checking before synchronized. So let’s add another check after synchronized
:
So it’s why it is called Double-checked locking. What’s more, in this way, if the first instance is checked not null, synchronized will be skipped which saves resources. But due to Java platform memory model problems. It’s not that stable, please check * Double-checked locking and the Singleton pattern for more details about this discussion.
Here volatile
is suggested to use for jdk > 1.5 for memory problems. Check here for more details about this key word.
Lazy initialization holder class
To achieve thread-safe simply, we can use static initializer. For example, like Eager initialization. But in this way, it will initialize the object when load class, regardless of whether you need it or not.
So we want to load the class without initializing this object. One possible way is to use the class-level internal class, in this class to create an object instance. As a result, it will not create this instance until this class is used, so we have lazy loading and thread-safe in the mean time.
When getInstance()
is invoked in the first time. It will load SingletonHolder.instance
which leads SingletonHolder
class to be initialized. When SingletonHolder
is initialized, it will initialize its static field. As it’s a static field, so it will only be initialized one time and thread safe :D
Enum
It is suggested by Josh Bloch, author of «Effective Java». Due to enum
, It can not only avoid the multi-thread synchronization problem, but also automatically supports serialization mechanism and prevent deserialization recreate a new object, also for sure, absolutely prevent multiple instances!
Let’s see an example:
An enum
type is a special type of class
type. This enum declaration actually compiles to something like
When your code first accesses INSTANCE, the class MySingleton
will be loaded and initialized by the JVM. This process initializes the static field above once (lazily).
Test it:
Output: