Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Common Pattern to Initialize A Singleton On A Background Thread

I currently have a singleton, which can take up to 10 seconds to initialize. However, I don't want my users to penalized (waiting) for this initialize, so I'd rather bootstrap this component on a background thread during application startup. Here's what I have:

Singleton:

public class MySingleton
{
    private static MySingleton _instance;
    private static readonly object _locker = new object();

    private MySingleton() 
    {
        Init();
    }
    public static MySingleton Instance 
    { 
        if(_instance == null) _instance = new MySingleton();
        return _instance;
    }
    public void Init()
    {
        lock(_locker)
        {
            if(_instance != null) return;

            // long running code here...
        }
    }
}

Application Startup:

Task.Factory.StartNew(() => MySingleton.Instance.Init());

This code does work, guards against double init, guards against the edge case of the user needing it before it's done initializing and also guards against someone forgetting to call Init().

However, it feels a little clunky for two reasons: a) I'm going to go into the Init method twice on startup. b) I'd like to do threading inside the singleton, but something has to initiate the initialization.

Is there a cleaner/nicer/better way to handle this?

Thanks in advance for everyone's help.

**EDIT: As pointed out in the comments, Init was mistakenly scoped as private. It should be public and has been corrected.

like image 207
pdalbe01 Avatar asked Mar 28 '12 04:03

pdalbe01


People also ask

What is the most common method signature to obtain a singleton?

The most popular approach is to implement a Singleton by creating a regular class and making sure it has: A private constructor. A static field containing its only instance. A static factory method for obtaining the instance.

What type of pattern is the Singleton pattern?

Singleton pattern is one of the simplest design patterns in Java. This type of design pattern comes under creational pattern as this pattern provides one of the best ways to create an object.

What is one of the most common mistakes you can make when implementing a singleton?

A common mistake with that implementation is to neglect synchronization, which can lead to multiple instances of the singleton class.


1 Answers

Use the static constructor to trigger it and a ManualResetEvent for the syncing. It gives you a solution where everything is done within the actual class. It's therefore not dependent of that someone should call your init method.

public class MySingleton
{
    private static MySingleton _instance;
    private static ManualResetEvent _initEvent = new ManualResetEvent(false);

    static MySingleton() 
    {
        ThreadPool.QueueUserWorkItem(state => Init());
    }

    public static MySingleton Instance 
    {
        _initEvent.Wait();
        return _instance;
    }
    private static void Init()
    {
        _instance = new MySingleton();
        // long running code here...


        _initEvent.Set();
    }
}

The event will stay signaled once triggered which means that the Instance property will return ASAP when the Init method is done.

like image 105
jgauffin Avatar answered Sep 30 '22 15:09

jgauffin