Design Patterns: The Singleton Pattern in Java
by Riley MacDonald, August 19, 2017

Introduction
The singleton pattern enforces object instantiation in order to guarantee only one instance of an Object can be created. While the singleton pattern can be advantageous for memory intensive objects it should be used sparingly. Developers also need to take care to ensure their singleton Objects perform as expected in multithreaded environments.

Example Instantiation Problem
Consider the game Super Mario. While playing the game you only ever want one instance of Mario while playing. The same instance of Mario should be used until he is destroyed or successfully rescues the princess (ending the game). An initial approach might look like this:

public class Mario {
    public enum State {
        SMALL,
        BIG,
        FLOWER_POWER,
        STAR_POWER,
        DESTROYED
    }
 
    public State state;
 
    public Mario() {
        state = State.SMALL;
    }
 
    public void destroy() {
        state = State.DESTROYED;
    }
 
    public void powerup() {
        if (state == State.SMALL) {
            state = State.BIG;
        }
    }
 
    public void takeDamage() { 
        if (state == State.SMALL) {
            destroy();
        }
    }
 
    // ...
}

Multiple instances (or references) of Mario could exist concurrently. In a multithreaded environment (for example) Mario might powerup(); and quickly takeDamage();. With no guaranteed order of operations we might see Mario be destroyed from a State.BIG state (in the case that takeDamage(); ran on one thread before powerup(); did).

The Singleton Pattern
The singleton pattern resolves issues like the one described above by circumscribing an Objects instantiation to one and only one instance. The singleton pattern is one of the simplest design patterns and is implemented as such (refactoring our Mario code example from above):

public class MarioSingleton {
    // Add a static variable to hold the single instance of Mario
    private static MarioSingleton mario;
 
    // Make the constructor private blocking instantiation
    private MarioSingleton() { }
 
    // Add a static instantiation method
    public static MarioSingleton getInstance() {
        if (mario == null) {
            mario = new Mario();
        }
 
        return mario;
    }
 
    // ... the rest of the Mario implementation
}

Now only one instance of Mario can ever be instantiated.

Multithreading Issues
Unfortunately the above MarioSingleton still doesn’t perform properly in a multithreaded environment. In some cases multiple threads could still end up receiving multiple instances of MarioSingleton. There’s a few options available to resolve these potential threading issues.

Option 1: Synchronization
The Java synchronization keyword can be applied the the static getInstance() method. This will ensure only one instance of MarioSingleton is created across multiple threads. The downside to this option is performance. If MarioSingleton instantiation code contains expensive operations, synchronized will have a negative effect on performance otherwise this solution is adequate. Keep in mind synchronized will be invoked everytime an instance of MarioSingleton is requested.

public class MarioSingleton {
    // synchronize the getInstance() method
    public static synchronized MarioSingleton getInstance() { }
}

Option 2: Eager Instantiation
Another option for non expensive singleton object instantiation is to use eager instantiation. The singleton instance is created by the JVM when the class is loaded. Note; this solution probably won’t work for a game style problem -> but it’s worth mentioning overall.

public class MarioSingleton {
    private static MarioSingleton mario = new MarioSingleton();
 
    private MarioSingleton() { }
 
    private static MarioSingleton getInstance() {
        return mario;
    }
}

Option 3: Double checked locking
Double checked locking uses synchronization but blocks these expensive calls from happening multiple times by first checking if a singleton instance exists, performing the synchronize call, and then checking again if a singleton instance exists (double checking). This operation is overkill for inexpensive object instantiation. Note: requires Java 5+ as the volatile keyword did not exist in previous Java versions.

public class MarioSingleton {
    // volatile to ensure multiple threads properly handle the instantiation of the singleton instance
    private volatile static MarioSingleton mario;
 
    private MarioSingleton() { }
 
    public static MarioSingleton getInstance() {
        if (mario == null) {
            synchronized (MarioSingleton.class) {
                if (mario == null) {
                    mario = new MarioSingleton();
                }
            }
        }
    }
}

Summary
Note this pattern requires Java version 1.2+ (previous versions contained a bug in the garbage collector which would cause these types of static instances to be collected). You should avoid subclassing Singleton Objects as that would violate the pattern (only one instance should exist). The singleton pattern is great pattern for global objects which should only have a single instance such as device drivers, caches, registries, etc.

Open the comment form

Leave a comment:

Comments will be reviewed before they are posted.

User Comments:

My Design Patterns Catalog | Riley MacDonald on 2017-11-10 15:08:56 said:
[…] Singleton: The singleton pattern enforces object instantiation in order to guarantee only one instance of an Object can be created. […]