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.
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.
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.
A common mistake with that implementation is to neglect synchronization, which can lead to multiple instances of the singleton class.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With