Reputation: 2114
Is there any functional difference between these two ways of implementing a Singleton?
public class MySingleton {
private static MySingleton instance;
public static MySingleton getInstance() {
if (instance == null) {
instance = new MySingleton();
}
return instance;
}
}
public class MySingleton {
private static final MySingleton instance = new MySingleton();
public static MySingleton getInstance() {
return instance;
}
}
Besides the fact that the first way would allow for some sort of clearInstance() method. Though you could just make instance not final in the second method.
Does the first method technically perform better because it is only initialized the first time it is needed instead of when the program starts?
Upvotes: 3
Views: 660
Reputation: 4598
From the unit testing point of view I prefer the lazy instatiatiation. Given that the singleton's initialization has further side effects (which are irrelevant to the actual test), and you want to test a class which needs the singleton (maybe just one particular method), it's easier to mock the singleton and inject it to the instance variable while preparing the test. Using a mock for your singleton instance you have easier control what the singleton's method return to your class under test.
The overhead of the thread safe instantiation can be minimized by the double checked lock pattern:
private static volatile MySingleton instance;
public static MySingleton getInstance() {
if (instance == null) {
synchronized ( MySingleton.class ) {
if (instance == null) {
instance = new MySingleton();
}
}
}
return instance;
}
Thus only the rare situation where two (or more) threads access the singleton for the first time (and at the same time) may enter the lock state. Afterwards the first ''if null'' will return false and you never enter the lock state again.
Important: the member has to be declared volatile for this pattern to work reliably.
Note: It has been proven that the above "double checked lock" pattern is not 100 percent reliable. See the discussion below in the comments and especially Brian Goetz' arcticle
Upvotes: 1
Reputation: 14253
The first one is lazy loading and the second is eager loading. Maybe your application never call the singleton, so if creating new instance of your singleton be heavy resource consuming action, then the lazy loading is better since it create new instance once needed.
Upvotes: 4
Reputation: 306
The first method you use is not thread safe. I would consider it to be a bug.
The second method is simpler, thread safe, fast and, if you make sure the constructor won't throw silly exceptions, correct.
If you absolutely need more logic you can go with the first method, must make sure you protect it with a mutex. Something like:
public class MySingleton {
private static final Object mylock = new Object();
private static MySingleton instance;
public static MySingleton getInstance() {
synchronized(mylock) {
if (instance == null) {
instance = new MySingleton();
}
return instance;
}
}
}
Clearly the code is more complex, uses more memory, it's slower, you can't declare the variable as final...
Both methods will initialize the Singleton lazily. In Java, all variable initialization and static constructors are involved by the class loader when the class is used, not on the start of the code. If your code path never invokes getInstance the Singleton will never get initialized.
Personally, I avoid singletons, but when I use them is always with an immediate allocation on the variable declaration.
Correction I ran a few experiments, and it turns out class initialization happened in parallel with the execution of the main thread. It didn't waited, as I believed it would. At least on a very simplified test scenario the initialization is eager, but asynchronous.
Upvotes: 3
Reputation: 3755
Its about Lazy Initialization vs Eager initialization. The difference is, in the first one the instance will not create until you call the getInstance()
method, but in the second one its already have been created even before you call the getInstance()
method.
Please refer this link if you want more info
Upvotes: 1
Reputation: 181159
Is there any functional difference between these two ways of implementing a Singleton?
Yes. If you use an initializer in the variable declaration, then the instance is created when the class is initialized, even if the instance is never accessed. If you initialize it in the getInstance()
method then the instance is only created if it is accessed. That has thread safety implications. It does does not otherwise make much difference if initializing an instance is cheap and without lasting external side effects, but that may not always be the case.
Does the first method technically perform better because it is only initialized the first time it is needed instead of when the program starts?
If you are going to use an instance in any case then you are going to pay the cost of initializing it at some point no matter what, so there is no performance difference in that sense. However, a thread-safe version of the first method will be slightly more expensive than the second method on the first invocation, and you will pay that extra overhead again on every subsequent invocation.
Upvotes: 2