Advertisement

Sri Lanka's First and Only Platform for Luxury Houses and Apartment for Sale, Rent

Monday, May 25, 2026

Writing better Singleton Pattern with Java 26 LazyConstant


Singleton is a widely used Design Pattern which guarantees a single instance of a given class is created within an application process. This is a very good design pattern for creating instances which have a very high cost for creation in terms of memory and cpu.

A typical Singleton class for a UserService will look like following;

 public class UserService {  
   record User(String firstName, String lastName) {  
     public String toString() {  
       return firstName + " " + lastName;  
     }  
   }  
   private static UserService INSTANCE;  
   public static UserService getInstance() {  
     if (INSTANCE == null) {  
       INSTANCE = new UserService();  
     }  
     return INSTANCE;  
   }  
   private UserService() {  
     // Long running loading  
     try {  
       Thread.sleep(5000);  
     } catch (InterruptedException e) {  
       e.printStackTrace();  
     }  
   }  
   public User getCurrentUser() {  
     return new User("John", "Doe");  
   }  
 }  

Even though this implementation looks like safe this will create multiple instances of UserService classes when used in a multi threaded environment due to race condition. To solve this issue the getInstance method can be re-written with double checking as following;

   private volatile static UserService INSTANCE;  
   public static UserService getInstance() {  
     var instance = INSTANCE;  
     if (instance == null) {  
       synchronized (UserService.class) {  
         instance = INSTANCE;  
         if (instance == null) {  
           INSTANCE = instance = new UserService();  
         }  
       }  
     }  
     return instance;  
   }  
Here we are making INSTANCE variable volatile so that it is guarantees visibility to all threads and two null checks one inside of a synchronized block to support atomicity between multiple threads. 

If all these code causes complexity the other option is to use Eager constant and initialisation like following;

   private final static UserService INSTANCE = new UserService();  
   public static UserService getInstance() {  
     return INSTANCE;  
   }  
Now the UserService is instantiated at the class loading time itself. This is ok where UserService initialisation is fast. But when it takes time initialise UserService let's say with a blocking I/O this will not be the ideal solution.

With Java 26 there is a new interface has been introduced named LazyConstant. As the name suggests instead of eagerly initialising the INSTANCE variable at class loading it will defer it till the first request for the getInstance method as following;

LazyConstant brings the goodness of both worlds by avoiding the complexity of double null checking and lazy initialisation even when initialisation may have blocking I/O and take longer to load.

   private static LazyConstant<UserService> INSTANCE = LazyConstant.of(UserService::new);  
   public static UserService getInstance() {  
     return INSTANCE.get();  
   }  

No comments: