Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singleton with Enum vs Singleton with double-checked locking

I am wondering which one is better in practice in a multithreaded environment. I understand Singleton as Enum type creates an instance when the class is loaded. Other than that I don't see anything else significant. Is there any pros and cons ?

Singleton as Enum type:

 public enum Singleton {
      INSTANCE;
      public void doSomething(){ ... }
 }

Singleton with double-checked locking:

 public class Singleton{
      private volatile static Singleton instance;

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

 }
like image 787
peter Avatar asked Feb 20 '23 12:02

peter


2 Answers

Often in multi-threaded applications, simpler, easier to understand code is more likley to work.

To my mind the first example is significantly simpler than the second and that is what matters.

The main pro of using an enum is its much simpler and the more complicated example is not justified. The double locking example allows you to change the singleton in interesting way for unit tests, but I believe what this gives you can be solved another way.

like image 192
Peter Lawrey Avatar answered Mar 07 '23 11:03

Peter Lawrey


There are more problems with Singletons, than just a correct implementation.

People often use Singletons, so they don't have to pass Objects around, where they should or they would have to pass Objects across multiple Methods.

There are quite a few examples for instantiating a jdbc connection with a Singleton.

In the methods where you need this connection, you can easily access it, because its a Singleton.

public enum DBConnection {
  INSTANCE;
  private Connection connection;
  public Connection getConnection(){
    if(connection == null){
      instantiateConnection();
    }
    return connection;
  }
}

and accessing it by

DBConnection.INSTANCE.getConnection();

But often it's better to do it with Dependency Injection and a pleasent framework. GUICE for example.

In your code you would not make a call on DBConnection.INSTANCE and than on getConnection(), you're Class would have a field DBConnection annotated with @Inject. And you just use it.

@Inject
private DBConnection dBConnection;

And the Class would be just annotated with @Singleton to be a Singleton, and the framework would assure it's a singleton.

And if you have different environments like, test and production you could let the framework inject different Objects for each environment.

like image 32
daniel Avatar answered Mar 07 '23 11:03

daniel