Skip to content

Instantly share code, notes, and snippets.

@mskoroglu
Last active January 24, 2025 12:49
Show Gist options
  • Save mskoroglu/a246e4652c95865402baaa40d96b425d to your computer and use it in GitHub Desktop.
Save mskoroglu/a246e4652c95865402baaa40d96b425d to your computer and use it in GitHub Desktop.
A Thread-Safe and Lightweight Lazy Initialization Class in Java
import java.util.Objects;
import java.util.function.Supplier;
public final class Lazy<T> implements Supplier<T> {
private final Supplier<T> initializer;
private volatile T value;
private volatile boolean initialized = false;
public Lazy(final Supplier<T> initializer) {
this.initializer = Objects.requireNonNull(initializer, "Initializer cannot be null");
}
@Override
public T get() {
if (!initialized) {
synchronized (this) {
if (!initialized) {
value = initializer.get();
initialized = true;
}
}
}
return value;
}
@Override
public String toString() {
return initialized ? String.valueOf(value) : "Lazy[not initialized]";
}
}
@mskoroglu
Copy link
Author

A Thread-Safe and Lightweight Lazy Initialization Class in Java

This Lazy<T> class provides a lightweight and thread-safe way to implement lazy initialization in Java. It uses a Supplier<T> to delay the creation of an object until it is first accessed, ensuring efficient resource usage. The implementation is optimized for single and multi-threaded scenarios, following best practices for thread safety.

Key Features:

  1. Thread-Safe Initialization: Double-checked locking with a volatile flag ensures that initialization happens only once, even under concurrent access.
  2. Customizable Initialization Logic: The Supplier<T> allows you to define any custom logic for creating the value.
  3. Lightweight and Simple: No third-party dependencies; easy to understand and integrate.

Usage Examples:

1. Lazy Initialization for a Static Field

public class Example {
    private static final Lazy<String> STATIC_LAZY_VALUE = new Lazy<>(() -> {
        System.out.println("Initializing static lazy value...");
        return "Hello, Lazy!";
    });

    public static String getStaticValue() {
        return STATIC_LAZY_VALUE.get();
    }

    public static void main(String[] args) {
        System.out.println("Static lazy value not initialized yet.");
        System.out.println("Value: " + getStaticValue());
        System.out.println("Value: " + getStaticValue());
    }
}

Output:

Static lazy value not initialized yet.
Initializing static lazy value...
Value: Hello, Lazy!
Value: Hello, Lazy!

2. Lazy Initialization for a Non-Static Field

public class Example {
    private final Lazy<Integer> lazyValue = new Lazy<>(() -> {
        System.out.println("Calculating the value...");
        return 42;
    });

    public int getValue() {
        return lazyValue.get();
    }

    public static void main(String[] args) {
        Example example = new Example();
        System.out.println("Non-static lazy value not initialized yet.");
        System.out.println("Value: " + example.getValue());
        System.out.println("Value: " + example.getValue());
    }
}

Output:

Non-static lazy value not initialized yet.
Calculating the value...
Value: 42
Value: 42

Why Use This Class?

  • Simplifies lazy initialization without relying on third-party libraries.
  • Ensures thread safety while keeping the implementation concise.
  • Ideal for both static and instance fields in single- or multi-threaded environments.

Feel free to use, modify, or enhance this class for your projects. 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment