当前位置: 代码迷 >> 综合 >> JavaSE复习——单例模式
  详细解决方案

JavaSE复习——单例模式

热度:25   发布时间:2024-01-19 14:21:46.0

单例模式是指,某个类只能被实例化一次,在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();}
}

 通过底层保证了单例的实现,且防止了反序列化。。

 

  相关解决方案