[ACCEPTED]-Other Ways of Singleton in Java-singleton
No, it is not. You didn't declare myClass
private static final
, nor 16 the getInstance()
is static
. The code also doesn't really compile.
Here's 15 the Singleton idiom:
public class MyClass {
private static final MyClass myClass = new MyClass();
private MyClass() {}
public static MyClass getInstance() {
return myClass;
}
}
It should be private
, so that nobody 14 else can access it directly. It should be 13 static
so that there's only one of it. It should 12 be final
so that it cannot be reassigned. You 11 also need to instantiate it directly during declaration 10 so that you don't need to worry (that much) about 9 threading.
If the loading is expensive and 8 you thus rather prefer lazy loading of the 7 Singleton, then consider the Singleton holder idiom which 6 does initialization on demand instead of 5 during classloading:
public class MyClass {
private MyClass() {}
private static class LazyHolder {
private static final MyClass myClass = new MyClass();
}
public static MyClass getInstance() {
return LazyHolder.myClass;
}
}
You should however put 4 big question marks whether you need a Singleton or 3 not. Often it's not needed. Just a static variable, an 2 enum, a factory class and/or dependency 1 injection is often the better choice.
Here's one more way to do it :
public enum Singleton{
INSTANCE("xyz", 123);
// Attributes
private String str;
private int i;
// Constructor
Singleton(String str, int i){
this.str = str;
this.i = i;
}
}
According 13 to Josh Bloch's Effective Java, this is 12 the best way to implement Singleton in Java. Unlike 11 implementations that involve a private static 10 instance field, which can be multiply instantiated 9 through the abuse of reflection and/or serialization, the 8 enum is guaranteed to be a singleton.
The 7 main limitation with enum singletons is 6 that they are always instantiated at class 5 loading time and can't be lazily instantiated. So 4 if, for example, you want to instantiate 3 a singleton using run-time arguments, you'll 2 have to use a different implementation (preferably 1 using double-checked locking).
There are 3 ways to create a singleton in 4 java.
eager initialization singleton
public class Test { private static final Test TEST = new Test(); private Test() { } public static Test getTest() { return TEST; } }
lazy 3 initialization singleton (thread safe)
public class Test { private static volatile Test test; private Test(){} public static Test getTest() { if(test == null) { synchronized(Test.class) { if(test == null){test = new Test();} } } return test; } }
Bill 2 Pugh Singleton with Holder Pattern (Preferably 1 the best one)
public class Test { private Test(){} private static class TestHolder { private static final Test TEST = new Test(); } public static Test getInstance() { return TestHolder.TEST; } }
Using your example and using the GoF's way 1 of implementing it:
public class MyClass{
private static Myclass instance;
private MyClass(){
//Private instantiation
}
public static synchronized MyClass getInstance() //If you want your method thread safe...
{
if (instance == null) {
instance = new MyClass();
}
return instance;
}
}
Hope this helps:
Here is how I do it. It is faster, because 2 it only requires a synchronized
block when the instance 1 is created.
public class MyClass
{
private static MyClass INSTANCE=null;
private MyClass()
{
}
public static MyClass getInstance()
{
if(INSTANCE==null)
{
synchronized(MyClass.class)
{
if(INSATCNE==null) INSTANCE=new MyClass();
}
}
return INSTANCE;
}
}
Your class (original code, before editing):
public class MyClass {
Myclass myclass;
static { myclass = new MyClass();}
private MyClass(){}
public MyClass getInstance()
{
return myclass;
}
}
is 4 not a real singleton:
- the field
myclass
is not private, can be read and changed from outside (assuming you got an instace to do it on - the field
myclass
is not static, can not be accessed in the static constructor (compilation error) - the
getInstance()
method is not static, so you need an instance to call it
The actual code:
public class MyClass {
static Myclass myclass;
static { myclass = new MyClass();}
private MyClass(){}
public static MyClass getInstance()
{
return myclass;
}
}
still 3 has myclass
not being private (nor final)... declaring 2 it final would help to prevent it being 1 unintentionally changed from inside the class.
private static final Myclass myclass;
public class singletonPattern {
private static singletonPattern obj;
public static singletonPattern getObject() {
return obj = (obj == null) ? new singletonPattern() : obj;
}
public static void main(String args[]) {
singletonPattern sng = singletonPattern.getObject();
}
}
0
Might be a little late to the game on this, but 108 a basic implementation would look something 107 like this:
public class MySingleton {
private static MySingleton INSTANCE;
public static MySingleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new MySingleton();
}
return INSTANCE;
}
...
}
Here we have the MySingleton class 106 which has a private static member called 105 INSTANCE, and a public static method called 104 getInstance(). The first time getInstance() is 103 called, the INSTANCE member is null. The 102 flow will then fall into the creation condition 101 and create a new instance of the MySingleton 100 class. Subsequent calls to getInstance() will 99 find that the INSTANCE variable is already 98 set, and therefore not create another MySingleton 97 instance. This ensures there is only one 96 instance of MySingleton which is shared 95 among all callers of getInstance().
But this 94 implementation has a problem. Multi-threaded 93 applications will have a race condition 92 on the creation of the single instance. If 91 multiple threads of execution hit the getInstance() method 90 at (or around) the same time, they will 89 each see the INSTANCE member as null. This 88 will result in each thread creating a new 87 MySingleton instance and subsequently setting 86 the INSTANCE member.
private static MySingleton INSTANCE;
public static synchronized MySingleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new MySingleton();
}
return INSTANCE;
}
Here we’ve used the 85 synchronized keyword in the method signature 84 to synchronize the getInstance() method. This 83 will certainly fix our race condition. Threads 82 will now block and enter the method one 81 at a time. But it also creates a performance 80 problem. Not only does this implementation 79 synchronize the creation of the single instance, it 78 synchronizes all calls to getInstance(), including 77 reads. Reads do not need to be synchronized 76 as they simply return the value of INSTANCE. Since 75 reads will make up the bulk of our calls 74 (remember, instantiation only happens on 73 the first call), we will incur an unnecessary 72 performance hit by synchronizing the entire 71 method.
private static MySingleton INSTANCE;
public static MySingleton getInstance() {
if (INSTANCE == null) {
synchronize(MySingleton.class) {
INSTANCE = new MySingleton();
}
}
return INSTANCE;
}
Here we’ve moved synchronization 70 from the method signature, to a synchronized 69 block that wraps the creation of the MySingleton 68 instance. But does this solve our problem? Well, we 67 are no longer blocking on reads, but we’ve 66 also taken a step backward. Multiple threads 65 will hit the getInstance() method at or 64 around the same time and they will all see 63 the INSTANCE member as null. They will then 62 hit the synchronized block where one will 61 obtain the lock and create the instance. When 60 that thread exits the block, the other threads 59 will contend for the lock, and one by one 58 each thread will fall through the block 57 and create a new instance of our class. So 56 we are right back where we started.
private static MySingleton INSTANCE;
public static MySingleton getInstance() {
if (INSTANCE == null) {
synchronized(MySingleton.class) {
if (INSTANCE == null) {
INSTANCE = createInstance();
}
}
}
return INSTANCE;
}
Here 55 we issue another check from INSIDE the block. If 54 the INSTANCE member has already been set, we’ll 53 skip initialization. This is called double-checked 52 locking.
This solves our problem of multiple 51 instantiation. But once again, our solution 50 has presented another challenge. Other threads 49 might not “see” that the INSTANCE member 48 has been updated. This is because of how 47 Java optimizes memory operations. Threads 46 copy the original values of variables from 45 main memory into the CPU’s cache. Changes 44 to values are then written to, and read 43 from, that cache. This is a feature of Java 42 designed to optimize performance. But this 41 creates a problem for our singleton implementation. A 40 second thread — being processed by a different 39 CPU or core, using a different cache — will 38 not see the changes made by the first. This 37 will cause the second thread to see the 36 INSTANCE member as null forcing a new instance 35 of our singleton to be created.
private static volatile MySingleton INSTANCE;
public static MySingleton getInstance() {
if (INSTANCE == null) {
synchronized(MySingleton.class) {
if (INSTANCE == null) {
INSTANCE = createInstance();
}
}
}
return INSTANCE;
}
We solve 34 this by using the volatile keyword on the 33 declaration of the INSTANCE member. This 32 will tell the compiler to always read from, and 31 write to, main memory, and not the CPU cache.
But 30 this simple change comes at a cost. Because 29 we are bypassing the CPU cache, we will 28 take a performance hit each time we operate 27 on the volatile INSTANCE member — which 26 we do 4 times. We double-check existence 25 (1 and 2), set the value (3), and then return 24 the value (4). One could argue that this 23 path is the fringe case as we only create 22 the instance during the first call of the 21 method. Perhaps a performance hit on creation 20 is tolerable. But even our main use-case, reads, will 19 operate on the volatile member twice. Once 18 to check existence, and again to return 17 its value.
private static volatile MySingleton INSTANCE;
public static MySingleton getInstance() {
MySingleton result = INSTANCE;
if (result == null) {
synchronized(MySingleton.class) {
result = INSTANCE;
if (result == null) {
INSTANCE = result = createInstance();
}
}
}
return result;
}
Since the performance hit is due 16 to operating directly on the volatile member, let’s 15 set a local variable to the value of the 14 volatile and operate on the local variable 13 instead. This will decrease the number of 12 times we operate on the volatile, thereby 11 reclaiming some of our lost performance. Note 10 that we have to set our local variable again 9 when we enter the synchronized block. This 8 ensures it is up to date with any changes 7 that occured while we were waiting for the 6 lock.
I wrote an article about this recently. Deconstructing The Singleton. You 5 can find more info on these examples and 4 an example of the "holder" pattern 3 there. There is also a real-world example 2 showcasing the double-checked volatile approach. Hope 1 this helps.
Singloton class is the class where you get 6 the same object every time. When you want 5 to restrict a class from creating more than 4 one object the we need the Singleton Class.
For 3 example :
public class Booking {
static Booking b = new Booking();
private Booking() { }
static Booking createObject() { return b; }
}
To create object of this class 2 we can use :
Booking b1, b2, b3, b4;
b1 = Booking.createObject();
b2 = Booking.createObject();
Booking b1, b2, b3, b4;
b1 = Booking.createObject();
b2 = Booking.createObject();
b1
and b2
are referring to same 1 object.
You should think about the following properties 4 while creating a singleton class
- Reflection
- Multi threading
- Clone
- Serialization
if no Clone 3 or Serialization interfaces in your class, i 2 think the following class is best as singleton 1 class.
public class JavaClass1 {
private static JavaClass1 instance = null;
private JavaClass1() {
System.out.println("Creating -------");
if (instance != null) { // For Reflection
throw new RuntimeException("Cannot create, please use getInstance()");
}
}
public static JavaClass1 getInstance() {
if (instance == null) {
createInstance();
}
return instance;
}
private static synchronized void createInstance() { // for multithreading
if (instance == null) {
instance = new JavaClass1();
}
}}
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.