Java 单例总结
1:懒汉式,不保证线程安全
package com.yan.singleton; public class LazySingleton { private static final LazySingleton instance = null; private LazySingleton(){} public static LazySingleton getLazySingleton(){ if(null==instance){ return new LazySingleton(); } return instance; } }
2:饿汉式,线程安全
package com.yan.singleton; public class HungrySingleton { private HungrySingleton(){} private static final HungrySingleton instance = new HungrySingleton(); public static HungrySingleton getInstance(){ return instance; } }
3:静态内部类,线程安全
package com.yan.singleton; public class InnerClassSingleton { private InnerClassSingleton(){} public static final InnerClassSingleton getInstance(){ return InnerClassSingletonHolder.INSTANCE; } private static class InnerClassSingletonHolder{ private static final InnerClassSingleton INSTANCE = new InnerClassSingleton(); } }
4:枚举,线程安全,可以反序列化(推荐此种方式)JDK1.5之后才可以使用
package com.yan.singleton; public enum EnumSingleton { INSTANCE; public void todo(){ System.out.println("todo"); } }
方式1,2,3都可以使用反射机制来破坏其单例特性,采用枚举类型可以避免反射的破坏。
例如:
package com.yan.test; import com.yan.singleton.LazySingleton; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.logging.Level; import java.util.logging.Logger; public class Test { public static void main(String[] args) { Constructor<LazySingleton>cs ; try { cs = (Constructor<LazySingleton>) Class.forName("com.yan.singleton.LazySingleton") .getDeclaredConstructor(); cs.setAccessible(true);//得到私有访问权限,如果不设置,则无法实例化对象 LazySingleton ls = cs.newInstance(); System.out.println("===ls:"+ls); System.out.println("===ls:"+cs.newInstance()); } catch (ClassNotFoundException ex) { Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); }catch (SecurityException ex) { Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); } catch (InstantiationException ex) { Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); } catch (IllegalAccessException ex) { Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); } catch (IllegalArgumentException ex) { Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); } catch (InvocationTargetException ex) { Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchMethodException ex) { Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); } } }