The design is simple:
package raj;
class TestSingleton {
public static void main(String[] arg) {
Singleton s = Singleton.getInstance();
System.out.println(s.toString());
s.setVal(100);
Singleton s2 = Singleton.getInstance();
System.out.println(s2.toString());
System.out.println(s2.getVal());
}
}
public class Singleton {
private static Singleton singletonObj;
private Singleton() {
}
private int val = 0;
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
public static Singleton getInstance() {
if (singletonObj == null) {
singletonObj = new Singleton();
}
return singletonObj;
}
}
It relies on having a private constructor and public static interface to provide the object. We can make this design thread-safe by synchronizing the getInstance() method:
public static synchronized Singleton getInstance() {
if (singletonObj == null) {
singletonObj = new Singleton();
}
return singletonObj;
}
However, this approach would considerably slow down the access to the object as synchronization can be painfully slow and is only needed during the first create. To over come this we may eschew lazy instantiation of the object and change our Singleton class to the following to let the class loader take the responsibility for instantiation:
public class Singleton {
private static Singleton singletonOb = new Singleton();j;
private Singleton() {
}
private int val = 0;
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
public static Singleton getInstance() {
return singletonObj;
}
}
This is great! But if the objected created is a scarce resource and is never used then it obviously is wasteful. A thread-safe compromise solution would be to use double-checked locking:
public static Singleton getInstance() {
if (singletonObj == null) {
synchronized (Singleton.class) {
if (singletonObj == null) singletonObj = new Singleton();
}}
return singletonObj;
}
Now we take the synchronization hit just during the create but there is still a small overhead of an extra conditional check during every access. Also note that we cannot use synchronized(this) as we are locking from within a static context so need the class literal Singleton.class.
No comments:
Post a Comment