单例模式是指,某个类只能被实例化一次,在JVM中,只能有一个相应的对象存在。
第一种实现方式:饿汉式
package hungry;public class HungryMode {private HungryMode(){//构造方法私有,以防外部通过new来实例化}private static HungryMode instance = new HungryMode(); //准备一个该类的实例化对象,因为在类中定义,所以只有一个该对象。public static HungryMode getInstance(){return instance; //让调用者通过静态方法即可调用定义好的instance}
}
package hungry;public class Test {public static void main(String[] args){HungryMode hm1 = HungryMode.getInstance();HungryMode hm2 = HungryMode.getInstance();HungryMode hm3 = HungryMode.getInstance();System.out.println(hm1==hm2);System.out.println(hm2==hm3);System.out.println(hm3==hm1);}
}
第二种实现方式:懒汉式
懒汉式写法只适用于单线程模式。如果执行到类方法中的if(instance == null),很有可能其他线程也进行到这里并同时实例化出新的FullMode类对象。这不符合单例模式要求,故只能只用于单线程。
也可通过加synchronized关键字解决,但降低了效率。
package full;public class FullMode {private FullMode(){}private static FullMode instance;public static FullMode getInstance(){if(instance == null){instance = new FullMode();}//只有当外部其他类调用本类的static方法时,才实例化出一个对象。之后再调用,都返回这唯一一个对象。return instance;}
}
package full;public class Test {public static void main(String[] args){FullMode fm1 = FullMode.getInstance();FullMode fm2 = FullMode.getInstance();FullMode fm3 = FullMode.getInstance();System.out.println(fm1 == fm2);System.out.println(fm2 == fm3);System.out.println(fm3 == fm1);}
}
第三种实现方式:双检查
第一次进行判空,使得同一时刻只能有一个线程进入synchronized区域。第二次判空,如果instance是null,则线程就实例化一个类对象instance。如果不为null,则直接返回已经实例化的instance。适合多线程情况。
package full;import java.io.File;public class Test2 {public static void main(String[] args){Th1 t1 = new Th1();t1.start();Th2 t2 = new Th2();t2.start();Th3 t3 = new Th3();t3.start();System.out.println(t1.fm21);System.out.println(t2.fm22);System.out.println(t3.fm23);}
}
package full;public class Th1 extends Thread{static FullMode2 fm21;public void run(){fm21 = FullMode2.getInstance();}}
package full;public class Th2 extends Thread{static FullMode2 fm22;public void run(){fm22 = FullMode2.getInstance();}
}
package full;public class Th3 extends Thread{static FullMode2 fm23;public void run(){fm23 = FullMode2.getInstance();}
}
package full;public class FullMode2 {private static volatile FullMode2 instance;private FullMode2(){}public static FullMode2 getInstance(){if(instance == null){synchronized(FullMode2.class){if(instance == null){instance = new FullMode2();}}}return instance;}
}
第四种实现方式:静态内部类
类的静态属性只会在第一次加载类的时候被初始化。这里的线程安全由JVM来保障。在类进行初始化时,其他线程无法进入。
package StaticInnerClass;public class staticInnerMode {private staticInnerMode(){}private static class SingletonInstance{private static final staticInnerMode instance = new staticInnerMode();}public static staticInnerMode getInstance(){return SingletonInstance.instance;}
}
package StaticInnerClass;public class Test {public static void main(String[] args){staticInnerMode s1 = staticInnerMode.getInstance();staticInnerMode s2 = staticInnerMode.getInstance();staticInnerMode s3 = staticInnerMode.getInstance();System.out.println(s1);System.out.println(s2);System.out.println(s3);}
}
第五种实现方式:枚举
package enumMode;public enum SingletonEnum {INSTANCE;int i = 0;public void screen(){System.out.println("第"+(++i)+"次调用单例对象");}
}
package enumMode;public class Test {public static void main(String[] args){SingletonEnum se1 = SingletonEnum.INSTANCE;SingletonEnum se2 = SingletonEnum.INSTANCE;SingletonEnum se3 = SingletonEnum.INSTANCE;System.out.println(se1);se1.screen();System.out.println(se2);se2.screen();System.out.println(se3);se3.screen();}
}
通过底层保证了单例的实现,且防止了反序列化。。