Home/Learn/Low Level Design/Multiton Pattern

Multiton Pattern

Advanced
Creational Patterns

Extends Singleton by maintaining a registry of named instances, ensuring one instance per key rather than one instance globally.

Overview

The Multiton (Registry of Singletons) pattern is used when you need exactly one instance per logical key — for example, one database connection per tenant, one logger per class, or one thread pool per task type. Internally it uses a ConcurrentHashMap keyed by the discriminator with computeIfAbsent() for thread-safe lazy initialization. Java's Logger framework uses Multiton: Logger.getLogger("com.example") always returns the same Logger for a given name. The pattern reduces the scope of Singleton from "global" to "global per context".

Thread-Safe Multiton Implementation

Use ConcurrentHashMap.computeIfAbsent() for atomicity. Unlike putIfAbsent() with a pre-created value, computeIfAbsent() only evaluates the factory function when the key is absent, preventing unnecessary instantiation.

Java — Generic Multiton + per-tenant connection pool
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

public class Multiton<K, V> {
    private final ConcurrentHashMap<K, V> registry = new ConcurrentHashMap<>();
    private final Function<K, V> factory;

    public Multiton(Function<K, V> factory) {
        this.factory = factory;
    }

    // Thread-safe: computeIfAbsent is atomic per key
    public V getInstance(K key) {
        return registry.computeIfAbsent(key, factory);
    }

    public int registeredCount() { return registry.size(); }
}

// Concrete use case: per-tenant database connection pool
public class TenantConnectionPool {
    private static final Multiton<String, HikariDataSource> POOLS =
        new Multiton<>(tenantId -> {
            HikariConfig cfg = new HikariConfig();
            cfg.setJdbcUrl("jdbc:postgresql://db/" + tenantId);
            cfg.setMaximumPoolSize(10);
            return new HikariDataSource(cfg);
        });

    public static HikariDataSource forTenant(String tenantId) {
        return POOLS.getInstance(tenantId);
    }
}

// Usage
HikariDataSource tenantAPool = TenantConnectionPool.forTenant("tenant-a");
HikariDataSource tenantAPool2 = TenantConnectionPool.forTenant("tenant-a");
System.out.println(tenantAPool == tenantAPool2); // true — same instance

HikariDataSource tenantBPool = TenantConnectionPool.forTenant("tenant-b");
System.out.println(tenantAPool == tenantBPool); // false — different instances

Enum-Keyed Multiton

When keys are a fixed finite set (e.g. service tiers), use an enum as the key. EnumMap is faster than HashMap for enum keys and provides compile-time safety.

Java — Enum-keyed Multiton for rate limiters
import java.util.EnumMap;

public enum ServiceTier { FREE, PRO, ENTERPRISE }

public class RateLimiterRegistry {
    private static final EnumMap<ServiceTier, RateLimiter> LIMITERS;

    static {
        LIMITERS = new EnumMap<>(ServiceTier.class);
        LIMITERS.put(ServiceTier.FREE,       new RateLimiter(10));   // 10 req/s
        LIMITERS.put(ServiceTier.PRO,        new RateLimiter(100));
        LIMITERS.put(ServiceTier.ENTERPRISE, new RateLimiter(1000));
    }

    public static RateLimiter forTier(ServiceTier tier) {
        return LIMITERS.get(tier);  // always the same instance per tier
    }
}

public class RateLimiter {
    private final int requestsPerSecond;
    public RateLimiter(int rps) { this.requestsPerSecond = rps; }
    public boolean tryAcquire() { /* token bucket logic */ return true; }
}

Key Points to Remember

  • 1Multiton guarantees one instance per key — expands Singleton scope from global to per-context.
  • 2ConcurrentHashMap.computeIfAbsent() is the idiomatic thread-safe implementation.
  • 3Java Logging framework (java.util.logging.Logger) is the canonical Multiton example.
  • 4Beware of memory leaks — unbounded key sets (e.g. per request-id) cause the registry to grow infinitely.
  • 5EnumMap offers O(1) lookups and is more efficient than HashMap for enum keys.

Interview Questions

Sign in to ask Aria
1

What is the difference between Singleton and Multiton patterns?

EasyAmazon
2

How do you prevent memory leaks in a Multiton with dynamic keys?

HardNetflix
3

Name a Java standard library class that uses the Multiton pattern.

EasyGoogle
4

Why use computeIfAbsent() instead of putIfAbsent() in a thread-safe Multiton?

MediumMicrosoft

Ask Aria about Multiton Pattern

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…