Friday, July 30, 2021

Why Enum Singleton are better in Java? Examples

Enum Singletons are new way to implement Singleton pattern in Java by using Enum with just one instance. Though Singleton pattern in Java exists from long time Enum Singletons are relatively new concept and in practice from Java 5 onwards after introduction of Enum as keyword and feature. This article is somewhat related to my earlier post on Singleton, 10 interview questions on Singleton pattern in Java where we have discussed common questions asked on interviews about Singleton pattern and 10 Java enum examples, where we have seen how versatile enum can be. This post is about why should we use Enum as Singleton in Java, What benefit it offers compared to conventional singleton methods etc.

Java Enum and Singleton Pattern

Enum Singleton pattern in JavaFollowing are some reasons which make sense to me for using Enum to implement Singleton pattern in Java. By the way, If you like articles on design patterns then you can also check my post on Builder design patterns and Decorator design pattern.

1) Enum Singletons are easy to write

This is by far the biggest advantage if you have been writing Singletons prior ot Java 5 than you know that even with double-checked locking you can have more than one instance. though that issue is fixed with Java memory model improvement and guarantee provided by volatile variables from Java 5 onwards it still tricky to write for many beginners. 

Compared to double-checked locking with synchronization Enum singletons are cake walk. If you don't believe then just compare the below code for conventional singleton with double-checked locking and Enum Singletons:



2. Singleton using Enum in Java

This is the way we generally declare Enum Singleton, it may contain instace variable and instance method but for sake of simplicity I haven’t used any, just beware that if you are using an instance method then you need to ensure thread-safety of that method if at all it affects the state of an object. 

By default creation of Enum instance is thread safe but any other method on Enum is programmers responsibility.

/**
* Singleton pattern example using Java Enumj
*/
public enum EasySingleton{
    INSTANCE;
}

You can acess it by EasySingleton.INSTANCE, much easier than calling getInstance() method on Singleton.



3. Singleton example with double-checked locking

Below code is an example of double-checked locking in Singleton pattern, here getInstance() method checks two times to see whether INSTANCE is null or not and that’s why it’s called double-checked locking pattern, remember that double-checked locking is broker before Java 5 but with the guaranteed of volatile variable in Java 5 memory model, it should work perfectly.

/**
* Singleton pattern example with Double-checked Locking
*/
public class DoubleCheckedLockingSingleton{
     
private volatile DoubleCheckedLockingSingleton INSTANCE;
 
     
private DoubleCheckedLockingSingleton(){}
 
     
public DoubleCheckedLockingSingleton getInstance(){
         
if(INSTANCE == null){
           
synchronized(DoubleCheckedLockingSingleton.class){
               
//double checking Singleton instance
               
if(INSTANCE == null){
                    INSTANCE
= new DoubleCheckedLockingSingleton();
               
}
           
}
         
}
         
return INSTANCE;
     
}
}

You can call DoubleCheckedLockingSingleton.getInstance() to get access of this Singleton class.

Now Just look at amount of code needed to create a lazy loaded thread-safe Singleton. With Enum Singleton pattern you can have that in one line because creation of Enum instance is thread-safe and guranteed by JVM.

People may argue that there are better way to write Singleton instead of Double-checked locking approach but every approach has there own advantages and disadvantages like I mostly prefer static field Singleton initialized during classloading as shown in below example, but keep in mind that is not a lazy-loaded Singleton:



Singleton pattern with a static factory method

This is one of my favorite method to impelemnt Singleton pattern in Java, Since Singleton instance is static and final variable it initialized when class is first loaded into memeory so creation of instance is inherently thread-safe.

/**
* Singleton pattern example with static factory method
*/


public class Singleton{
    //initailzed during class loading
    private static final Singleton INSTANCE = new Singleton();
 
    //to prevent creating another instance of Singleton
    private Singleton(){}

    public static Singleton getSingleton(){
        return INSTANCE;
    }
}

You can call Singleton.getSingleton() to get access of this class.


2) Enum Singletons handled Serialization by themselves

Another problem with conventional Singletons are that once you implement serializable interface they are no longer remain Singleton because readObject() method always return a new instance just like a constructor in Java. you can avoid that by using readResolve() method and discarding newly created instance by replacing with Singleton as shwon in below example :

    //readResolve to prevent another instance of Singleton
   
private Object readResolve(){
       
return INSTANCE;
   
}

This can become even more complex if your Singleton Class maintains state, as you need to make them transient, but with Enum Singleton, Serialization is guaranteed by JVM.

3) Creation of Enum instance is thread-safe

As stated in point 1 since creation of Enum instance is thread-safe by default you don't need to worry about double-checked locking.

In summary, given the Serialization and thread-safety guaranteed and with a couple of lines of code enum, the Singleton pattern is the best way to create Singleton in Java 5 world. you can still use other popular methods if you feel so but I still have to find a convincing reason not to use Enum as Singleton, let me know if you got any.


Other Java articles from Javarevisited blog:

31 comments:

  1. U have forget the "static" in the "Singleton example with double checked locking" it should be :
    public static DoubleCheckedLockingSingleton getInstance(){


    also in the first example the enum one to make it like the rest it is more 1:1 to work like the rest the example to become:
    public enum Singleton {
    INSTANCE;

    public static Singleton getInstance(){
    return INSTANCE;
    }
    }

    ReplyDelete
  2. Thanks for your tutorial dude. I wanted to implement Singleton design pattern using Java enum and looking for an example, didn't know that it would be this easy. you Singleton pattern example with Java Enum is just a piece of cake.

    ReplyDelete
  3. EnumSingleton or SingletonClassHolder are fine when your singleton's scope == ClassLoader (static). For other cases (lazy singleton per conversation/request/process), the DoubleCheckedSingleton is better.

    ReplyDelete
  4. Enums can't extend other enums or classes. And they are final.
    Sometimes that's enough not to use such singletons...

    ReplyDelete
  5. Enum singleton are perfect as soon as you don't need a singleton that inherit from something. In that case, you cannot use enum anymore and you must use other way...

    ReplyDelete
  6. In "Singleton pattern with static factory method" you didn't use factory method pattern but simple factory, which in fact is not "official" pattern.

    ReplyDelete
  7. In DoubleCheckedLockingSingleton example, instance variable and getInstance() method must be static. Otherwise, the user has to call object.getInstance() where object is an instantiation of DoubleCheckedLockingSingleton . But the constructor is private; therefore, no one can call getInstance()

    ReplyDelete
  8. This is the practical way:

    public enum ConnectionManager {
    INSTANCE;

    private EntityManagerFactory emf;

    private ConnectionManagerEnum() {
    emf = Persistence.createEntityManagerFactory("cassandra_pu");
    }

    public EntityManager getEntityManager() {
    return emf.createEntityManager();
    }
    }

    Usage: ConnectionManager.INSTANCE.getEntityManager()

    ReplyDelete
  9. in last comment, is it ConnectionManagerEnum or ConnectionManager?

    ReplyDelete
  10. we can't have private constructor
    private Singleton(){}

    ReplyDelete
  11. You have to have "static" modifier in both the getInstance() method and volatile variable if you want double checked locking. If method is not static then, you cannot access getInstance by just Singleton.getInstance(), and if the volatile instance variable is not static, then the static getinstance method cannot access the variable.

    /**
    * Singleton pattern example with Double checked Locking
    */
    public class DoubleCheckedLockingSingleton{
    private volatile DoubleCheckedLockingSingleton INSTANCE;

    private DoubleCheckedLockingSingleton(){}

    public DoubleCheckedLockingSingleton getInstance(){
    if(INSTANCE == null){
    synchronized(DoubleCheckedLockingSingleton.class){
    //double checking Singleton instance
    if(INSTANCE == null){
    INSTANCE = new DoubleCheckedLockingSingleton();
    }
    }
    }
    return INSTANCE;
    }
    }

    ReplyDelete
  12. It should be ConnectionManager I guess. Because this method is like constructor, which will be called by Enum while accessed/called.

    ReplyDelete
  13. In case of Singleton pattern with static factory method what is the need to declare the Singleton Object as final? If you see java.lang.Runtime class which implements Singleton pattern with early initialization declaration is

    private static Runtime currentRuntime = new Runtime();

    Yes as in this case object will be created when class is loaded synchronization is not needed. But I do not understand why do we need to declare it as final as you have shown in your example code.

    Also as others have mentioned in their comment in your double checked locking you need to declare your getInstance() method as well as the singleton object as static.

    ReplyDelete
  14. Hi there,

    This is regarding your example under "Singleton example with double checked locking". The method getInstance() first checks if INSTANCE hasn't been initialised yet. If not then it steps into the synchronized block and initialises INSTANCE. I see an issue here.

    If two threads access the method getInstance on the same object and thread A stops right after the INSTANCE==null check and thread B now gets the CPU, that thread B will run the same check and then step into the synchronized block where it then initialises INSTANCE. After it will have left the synchronized block thread A gets the CPU back which then steps into the synchronized block where it initialises INSTANCE again. It basically overwrites the value of INSTANCE. Therefore this implementation isn't thread safe.

    ReplyDelete
  15. @Tschoah: When A steps into the synchronized block it will check the INSTANCE for null again.

    Anyway the example is bad, because there is no static modifier on the INSTANCE variable and the getInstance() method.

    ReplyDelete
  16. You cannot declare them locally, within a method.

    ReplyDelete
  17. Please anyone explain INSTANCE object in enum singleton example

    ReplyDelete
  18. why the author does not editing double check locking code in the above article, it has some serious mistakes!!!

    ReplyDelete
  19. @Anonymous, what is the mistake you see on doubled checked locking code? care to explain?

    ReplyDelete
  20. @Anonymous, INSTANCE object in enum is just one enum constant of enum type Singleton.

    ReplyDelete
  21. "Static" in missing how can you access the getInstance() method. Double Checking

    public class DoubleCheckedLockingSingleton{
    private static volatile DoubleCheckedLockingSingleton INSTANCE;

    private DoubleCheckedLockingSingleton(){}

    public static DoubleCheckedLockingSingleton getInstance(){
    if(INSTANCE == null){
    synchronized(DoubleCheckedLockingSingleton.class){
    //double checking Singleton instance
    if(INSTANCE == null){
    INSTANCE = new DoubleCheckedLockingSingleton();
    }
    }
    }
    return INSTANCE;
    }
    }


    ReplyDelete
  22. A small correction : static is missing from getInstance method in double check example

    ReplyDelete
  23. Looks like , Its taken from Effective Java by Joshua Bloch.
    Due credits should be given :)

    ReplyDelete
  24. We do get different Object of logger in different class , then how come logger class is considered as singleton.
    For example , we get logger instance for SomeClass as

    Logger someClassLogger = Logger.getLogger(SomeClass.class);

    In AnotherClass logger instance would be:

    Logger anotherClassLogger = Logger.getLogger(AnotherClass.class);

    Now, if it returns the same object then how come during printing message, different class names are printed

    Example :

    (SomeClass:22) Hello, in SomeClass
    (AnotherClass:451) I am not same with SameClass


    ReplyDelete
  25. Enum singelton is lazy loaded or not?

    ReplyDelete
  26. @Anonymous, Enum Singleton is not lazy loaded. If you want a lazy loaded singleton then Singleton holder pattern is best.

    ReplyDelete
  27. enum singleton pattern is Lazy Loaded. please correct the post. see this for proof: https://stackoverflow.com/questions/16771373/singleton-via-enum-way-is-lazy-initialized

    ReplyDelete
  28. http://www.oracle.com/technetwork/articles/java/singleton-1577166.html

    ReplyDelete
  29. @Aniket Thakur You are right, Why did no one notice that your reply?

    ReplyDelete
  30. It is October 2022 and Enum based Singletons are no longer "new way". This javarevisited blog is priceless. Thank you.

    ReplyDelete
  31. Thank you Anonymous, comments like yours motivates me to keep working :-)

    ReplyDelete