饿汉模式是class被加载时就会被初始化,下面是具体的实例class:
public class HungrySingleton {
private static final HungrySingleton hungrySingleton=new HungrySingleton();
public HungrySingleton(){
}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
}
懒汉模式就是class未被使用时不会初始化,主要要是为了内存使用效率,饿汉模式在加载后被初始化有可能会用不到,对整个内存是浪费,以下是懒汉模式的实列class:
public class LazySingleton implements Serializable {
private static LazySingleton lazySingleton=null;
public static LazySingleton getInstance(){
if (lazySingleton==null)
synchronized (LazySingleton.class){
lazySingleton=new LazySingleton();
return lazySingleton;
}
else
return lazySingleton;
}
}
@Test
public void testHungrySingleton() throws Exception {
Constructor c= HungrySingleton.class.getDeclaredConstructor(null);
c.setAccessible(true);
Object c1=c.newInstance();
Object c2=c.newInstance();
System.out.println(c1+" "+c2+" "+(c1==c2));
c1=HungrySingleton.getInstance();
c2=HungrySingleton.getInstance();
System.out.println(c1+" "+c2+" "+(c1==c2));
}
进行log:
com.mesui.model.HungrySingleton@ca263c2 com.mesui.model.HungrySingleton@589b3632 false
com.mesui.model.HungrySingleton@45f45fa1 com.mesui.model.HungrySingleton@45f45fa1 true
@Test
public void LazySingleton() throws Exception {
Constructor c= LazySingleton.class.getDeclaredConstructor(null);
c.setAccessible(true);
Object c1=c.newInstance();
Object c2=c.newInstance();
System.out.println(c1+" "+c2+" "+(c1==c2));
c1=LazySingleton.getInstance();
c2=LazySingleton.getInstance();
System.out.println(c1+" "+c2+" "+(c1==c2));
}
运行log:
com.mesui.model.LazySingleton@ca263c2 com.mesui.model.LazySingleton@589b3632 false
com.mesui.model.LazySingleton@45f45fa1 com.mesui.model.LazySingleton@45f45fa1 true
public class LazySingleton implements Serializable {
private static LazySingleton lazySingleton=null;
public LazySingleton() {
throw new RuntimeException("you can't new instance object by constructor");
}
public static LazySingleton getInstance(){
if (lazySingleton==null)
synchronized (LazySingleton.class){
lazySingleton=new LazySingleton();
return lazySingleton;
}
else
return lazySingleton;
}
}
我们在利用LazySingleton()进行一次测试,运行log如下:
java.lang.RuntimeException: you can't new instance object by constructor
at com.mesui.model.LazySingleton.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mesui.SingletonTest.LazySingleton(SingletonTest.java:31)
@Test
public void FileHungrySingleton() throws Exception {
LazySingleton c1=LazySingleton.getInstance();
FileOutputStream fos=new FileOutputStream("lazysingleton.obj");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(c1);
oos.flush();
fos.close();
FileInputStream fis=new FileInputStream("lazysingleton.obj");
ObjectInputStream ois=new ObjectInputStream(fis);
LazySingleton c2=(LazySingleton) ois.readObject();
System.out.println(c1+" "+c2+" "+(c1==c2));
}
运行log:
com.mesui.model.LazySingleton@2b4a2ec7 com.mesui.model.LazySingleton@c8e4bb0 false
public class LazySingleton implements Serializable {
private static LazySingleton lazySingleton=null;
public static LazySingleton getInstance(){
if (lazySingleton==null)
synchronized (LazySingleton.class){
lazySingleton=new LazySingleton();
return lazySingleton;
}
else
return lazySingleton;
}
private Object readResolve(){
return lazySingleton;
}
}
我们在利用测试方法FileHungrySingleton()在进行一次,运行log如下:
com.mesui.model.LazySingleton@2b4a2ec7 com.mesui.model.LazySingleton@2b4a2ec7 true
public enum EnumSingleton {
INSTANCE;
private Object object;
public void setObject(Object o){
this.object=o;
}
public Object getObject(){
return this.object;
}
public static EnumSingleton getInstance(){
return INSTANCE;
}
}
我们可以用以下测试用例来覆盖上面的问题,看测试是否存在问题:
@Test
public void EnumSingleton() throws Exception {
EnumSingleton c1=EnumSingleton.getInstance();
EnumSingleton c2=EnumSingleton.getInstance();
c1.setObject(new Object());
System.out.println(c1.getObject());
c2.setObject(new Object());
System.out.println(c2.getObject());
System.out.println(c1.getObject()+" "+c2.getObject()+" "+(c1.getObject()==c2.getObject()));
EnumSingleton e1=EnumSingleton.INSTANCE;
e1.setObject(new Object());
System.out.println(e1.getObject());
FileOutputStream fos=new FileOutputStream("enumsingleton.obj");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(e1);
oos.flush();
fos.close();
FileInputStream fis=new FileInputStream("enumsingleton.obj");
ObjectInputStream ois=new ObjectInputStream(fis);
EnumSingleton e2=(EnumSingleton) ois.readObject();
System.out.println(e2.getObject());
System.out.println(e1.getObject()==e2.getObject());
Constructor c= EnumSingleton.class.getDeclaredConstructor(null);
c.setAccessible(true);
Object o1=c.newInstance();
Object o2=c.newInstance();
System.out.println(o1+" "+o2+" "+(o1==o2));
}
测试log:
java.lang.Object@589b3632 java.lang.Object@589b3632 true
true
java.lang.NoSuchMethodException: com.mesui.model.EnumSingleton.
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getDeclaredConstructor(Class.java:2178)