• About Blog

    What's Blog?

    A blog is a discussion or informational website published on the World Wide Web consisting of discrete, often informal diary-style text entries or posts.

  • About Cauvery Calling

    Cauvery Calling. Action Now!

    Cauvery Calling is a first of its kind campaign, setting the standard for how India’s rivers – the country’s lifelines – can be revitalized.

  • About Quinbay Publications

    Quinbay Publication

    We follow our passion for digital innovation. Our high performing team comprising of talented and committed engineers are building the future of business tech.

Tuesday, May 25, 2021

Singleton Design Pattern - Build It, Break It and Fix It!

Singleton Design Pattern
Photo Courtesy Unsplash


Singleton pattern is one of the simplest design patterns and falls under creational pattern as this pattern provides one of the best ways to create an object. This pattern involves a single class which is responsible for creating an object while making sure that the instantiation of a class to only one object. This class provides a way to access its only object which can be accessed directly without instantiating the object of the class.

Let’s see various design options for implementing the pattern. If you have a good hold on static class variables and access modifiers this is not a difficult task.

Lazy Instantiation

public class Singleton implements Serializable {

  private static Singleton singletonObject;

  //Adding a private constructor so that no one creates object
  private Singleton() {
  }

  public static Singleton getInstance() {
    if (singletonObject == null) {
      singletonObject = new Singleton();
    }
    return singletonObject;
  }

}

Here we have declared getInstance() as static so that we can call it without instantiating the class. First time, when getInstance() method is called, it creates a new Singleton object and later it just returns the same object reference. Note that singletonObject is not created until we call the getInstance() method, as we are using the lazy instantiation of the object.

The main problem with the above method is that it is not thread safe. If we have two threads T1 and T2 which invokes the getInstance() method at the same time, the execution sequence creates two objects for Singleton.

The other option is to make getInstance() method as synchronized. Here, using synchronized keyword makes sure that only one thread is allowed at a time to execute getInstance() method. The main disadvantage of this is method is, that using synchronized every time while creating the Singleton object is expensive and may decrease the performance of your program. However if performance of getInstance() is not critical for the application this method provides a clean and simple solution.

Eager Instantiation

public class Singleton implements Serializable {

  private static Singleton singletonObject = new Singleton();

  //Adding a private constructor so that no one creates object
  private Singleton() {
  }

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


Here we have created instance of Singleton with the help of static initializer. JVM executes static initializer when the class is loaded and hence this is guaranteed to be thread safe. Use this method only when the Singleton class is light and is used throughout the execution of the program.

Double Check and Locking Instantiation

public class Singleton implements Serializable {

  private static volatile Singleton singletonObject;

  //Adding a private constructor so that no one creates object
  private Singleton() {
  }

  public static Singleton getInstance() {
    if (singletonObject == null) {
      // Making thread safe
      synchronized(Singleton.class) {
        // Check again as object is still null
        if (singletonObject == null) {
          singletonObject = new Singleton();
        }
      }
    }
    return singletonObject;
  }
    
}

In the above implementation, we have declared the singletonObject as volatile. Using volatile is yet another way (like synchronized, atomic wrapper) of making class thread safe. Thread safe means that a method or class instance can be used by multiple threads at the same time without any problem. This method drastically reduces the overhead of calling the synchronized method every time.

Now that we know how to implement a Singleton pattern in 3 different ways. Let’s see whether we can break the Singleton pattern ?

Reflection

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or introspect upon itself, and manipulate internal properties of the program. For example, it’s possible for a Java class to obtain the names of all its members and display them.

We will use Reflection and see whether we can break the Singleton or not ?

class Singleton implements Serializable {

  private static Singleton singletonObject = new Singleton();

  //Adding a private constructor so that no one creates object
  private Singleton() {
  }

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

public class SingletonExample {
  
  public static void main(String[] args) {
    try {
        Singleton obj1 = Singleton.getInstance();
        System.out.println("Singleton.getInstance().hashCode: " + obj1.hashCode());

        Constructor constructor = Singleton.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        Singleton obj2 = (Singleton) constructor.newInstance();
        System.out.println("Reflection.newInstance().hashCode: " + obj2.hashCode());
    }
    catch (Exception e) {
        e.printStackTrace();
    }
  }
  
}

If you execute the above program, you should see in the output that the hashCode of both objects are different and it clearly violates Singleton pattern.

Singleton.getInstance().hashCode: 1418481495
Reflection.newInstance().hashCode: 303563356

Let’s fix this loop hole by making some simple code change in the Singleton constructor.

private Singleton() {
    if (singletonObject != null) {
        throw new IllegalStateException("Already Initialised!");
    }
}

Now if you execute the program with the above changes, the line 24 will call the constructor and it will throw an IllegalStateException. Thus prevents the creation of the second instance.

Caused by: java.lang.IllegalStateException: Already initialised!

What if I change the access level of the singleton field from private to public using the Reflection? Oops… it will allow me to set the singleton object to null and it will create a new object. Let’s modify our main method to hack the Singleton class.

public static void main(String[] args) {
    try {
        Singleton obj1 = Singleton.getInstance();
        System.out.println("Singleton.getInstance().hashCode: " + obj1.hashCode());

        Field field = Singleton.class.getDeclaredField("singletonObject");
        field.setAccessible(true);
        field.set(field, null);
        
        Constructor constructor = Singleton.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        Singleton obj2 = (Singleton) constructor.newInstance();
        System.out.println("Reflection.newInstance().hashCode: " + obj2.hashCode());
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}

Using Reflection, we are changing the value of the instance field to NULL after the object gets created. When we invoke the constructor, the condition fails as singleton instance is null hence it will allow you to create another instance.

We can prevent it by declaring the singletonObject instance as FINAL so that it’s value can’t be changed once assigned.

private final static Singleton singletonObject = new Singleton();

Now if you execute the program, it will throw an IllegalAccessException. Reflection can’t convert final field to non-final field. Please note, this approach only works with Eager Instantiation method.

Serialization

Java provides a mechanism, called object serialization where an object can be represented as a sequence of bytes that includes the object’s data as well as information about the object’s type and the types of data stored in the object.

After a serialized object has been written into a file, it can be read from the file and deserialized, i.e., the type information and bytes that represent the object and its data can be used to recreate the object in memory.

Most impressive is that the entire process is JVM independent, meaning an object can be serialized on one platform and deserialized on an entirely different platform.

We will use Serialization and see whether we can break the Singleton or not ?

class Singleton implements Serializable {

  private final static Singleton singletonObject = new Singleton();

  //Adding a private constructor so that no one creates object
  private Singleton() {
    if (singletonObject != null) {
      throw new IllegalStateException("Already Initialised!");
    }
  }

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

public class SingletonExample {
  
  public static void main(String[] args) {
    try {
        Singleton obj1 = Singleton.getInstance();
        System.out.println("Singleton.getInstance().hashCode: " + obj1.hashCode());
      
        // Serialize the object to file
        ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream("file.txt"));
        objectOutput.writeObject(obj);
        objectOutput.close();

        // DeSerailize the object from file
        ObjectInput objectInput = new ObjectInputStream(new FileInputStream("file.txt"));
        Singleton obj2 = (Singleton) objectInput.readObject();
        in.close();

        System.out.println("Serialization.getInstance().hashCode: " + obj2.hashCode());
    }
    catch (Exception e) {
        e.printStackTrace();
    }
  }
  
}

If you execute the above program, you should see in the output that the hashCode of both objects are different and it clearly violates Singleton pattern.

Singleton.getInstance().hashCode: 1418481495
Serialization.getInstance().hashCode: 565760380

Let’s fix this loop hole by making some simple code change in the Singleton class. We have to implement readResolve() method and return the singletonObject reference.

protected Object readResolve() {
    return singletonObject;
}

Conclusion

  • We saw how to implement the Singleton Pattern in different ways like Lazy Instantiation, Eager Instantiation and Double Check and Locking Instantiation.
  • We saw how we can break the Singleton Pattern using the Reflection and Serialization methods.
  • Also, we saw how it can be prevented by making few code changes so the Singleton Pattern won’t allow you to create more than one instance.

References:




Friday, May 7, 2021

Working With ThreadPoolTaskExecutor of Spring


Working With ThreadPoolTaskExecutor of Spring
Photo Courtesy Unsplash

ThreadPoolTaskExecutor is a java bean that allows for configuring a ThreadPoolExecutor in a bean style by setting up the values for the instance variables like corePoolSize, maxPoolSize, keepAliveSeconds, queueCapacity and exposing it as a Spring TaskExecutor.

One of the added Advantage of using ThreadPoolTaskExecutor of Spring is that it is well suited for management and monitoring via JMX.

The default configuration of core pool size is 1, max pool size and queue capacity as 2147483647.

This is roughly equivalent to Executors.newSingleThreadExecutor(), sharing a single thread for all tasks. And setting queueCapacity to 0 mimics Executors.newCachedThreadPool(), with immediate scaling of threads in the pool to a very high number.

If you are using XML file for configuring the bean, you can setup the ThreadPoolTaskExecutor like below:

<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
   <property name="corePoolSize" value="5" />
   <property name="maxPoolSize" value="10" />
   <property name="WaitForTasksToCompleteOnShutdown" value="true" />
</bean>

If you are using Java Annotation to define the bean, you can setup like below:

@Bean
public TaskExecutor threadPoolTaskExecutor() {
   ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
   executor.setCorePoolSize(5);
   executor.setMaxPoolSize(10);
   executor.initialize();
   return executor;
}

CorePoolSize

Is the minimum number of threads that remain active at any given point of time. If you don’t provide a value explicitly then it will have default value as 1. The TaskExecutor delegates the value to the underlying class ThreadPoolExecutor.

MaxPoolSize

Is the maximum number of threads that can be created. The TaskExecutor delegates the value to the underlying ThreadPoolExecutor. The maxPoolSize relies on queueCapacity because ThreadPoolTaskExecutor creates a new thread only if the number of items in the queue exceeds queue capacity.

Let’s test out the theory with some code so that it will be more clear for all of us. Here is a code snippet that will create new thread from TaskExecutor.

@Bean
public TaskExecutor threadPoolTaskExecutor() {
   ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
   executor.setCorePoolSize(5);public void createTasks(ThreadPoolTaskExecutor taskExecutor, int numTasks) {

    for (int i=0; i<numTasks; i++) {
       taskExecutor.execute(() -> {
       try {
          long sleepTime = ThreadLocalRandom.current().nextLong(1, 10) * 100;
          Thread.sleep(sleepTime);
       } 
       catch (InterruptedException e) {
          Thread.currentThread().interrupt();
       }
       });
   }
}

Now let’s create a main method where we can try out various use cases by setting values to the ThreadPoolTaskExecutor.

public static void main(String[] args) {
    // Creating ThreadPoolTaskExecutor
    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    taskExecutor.afterPropertiesSet();

    // Creating Tasks within ThreadPoolTaskExecutor
    createTasks(taskExecutor, 6);

    // Getting PoolSize
    System.out.println("Properties " +
        "- corePoolSize: " + taskExecutor.getCorePoolSize() +
        ", maxPoolSize: " + taskExecutor.getMaxPoolSize() +
        ", poolSize: " + taskExecutor.getPoolSize() +
        ", activeCount: " + taskExecutor.getActiveCount());

    // Shutting Down ThreadPoolTaskExecutor
    taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
    taskExecutor.shutdown();
}

If execute the above code snippet, you will the below output on the console. You can see that corePoolSize is 1 by default and maxPoolSize is 2147483647. Since the QueueCapacity is also 2147483647, you will see that it will make use of the one thread to process all 6 tasks.

17:37:21.696 [main] INFO org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor - Initializing ExecutorService

Properties - corePoolSize: 1, maxPoolSize: 2147483647, poolSize: 1, activeCount: 1

17:37:21.747 [main] INFO org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor - Shutting down ExecutorService

Let’s modify our code to setup some of the parameters so that we can see whether it will have any behavioural change in the TaskExecutor.

ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(1);
taskExecutor.setMaxPoolSize(4);
taskExecutor.afterPropertiesSet();

You will still observe that the TaskExecutor will still make use of one thread only though the max pool size is set to 4.

17:42:43.396 [main] INFO org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor - Initializing ExecutorService

Properties - corePoolSize: 1, maxPoolSize: 4, poolSize: 1, activeCount: 0

17:42:43.447 [main] INFO org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor - Shutting down ExecutorService

Let’s modify our code to setup queue capacity parameter so we see the behavioural change in the TaskExecutor.

ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(1);
taskExecutor.setMaxPoolSize(4);
taskExecutor.setQueueCapacity(2);
taskExecutor.afterPropertiesSet();

Now when you run the same piece of code, you will see that the pool size increases but it will not exceed max pool size.

17:47:29.986 [main] INFO org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor - Initializing ExecutorService

Properties - corePoolSize: 1, maxPoolSize: 4, poolSize: 4, activeCount: 4

17:47:30.036 [main] INFO org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor - Shutting down ExecutorService

TaskExecutor creates a new thread only if the number of items in the queue exceeds queue capacity. As a result, you will observe that pool size increases.

To conclude, it’s always a good practice to define the core pool size, max pool size and queue capacity for the TaskExecutor explicitly from our end instead of leaving it to use the default values.

Featured Post

Benefits & Best Practices of Code Review

Photo by Bochelly Code reviews are methodical assessments of code designed to identify bugs, increase code quality, and help developers lear...