学而时习之,不亦说乎!
--《论语》
五种单例模式:
单例的作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。
常见单例模式实现:
1.饿汉式单例模式。
2.懒汉式单例模式。
3.双重检测锁单例模式。
4.静态内部类单例模式。
5.枚举单例模式。
1.饿汉式单例模式。
package com.zby.pattern; import java.io.ObjectStreamException; import java.io.Serializable; /** * * <class description> 饿汉式单例模式。优点:类只会加载一次,在类加载的时候直接实例化一次,没有线程安全问题。 * 缺点:类加载就实例化,如果只需要加载这个类而不需要实例化对象,这个类又很耗内存,会浪费资源。 * * @author: zby * @version: 1.0, 2017年6月22日 */ public class Singleton01 implements Serializable { private static final long serialVersionUID = 1L; // 类加载实例化对象 private static final Singleton01 s = new Singleton01(); // 私有化构造方法 private Singleton01() { // 避免反射破坏单例 if (null != s) { throw new RuntimeException("No,you can't do this!"); } } // 提供全局访问点 public static Singleton01 getInstance() { return s; } /** * * <method description>防止对象反序列化时破坏单例 * * @return * @throws ObjectStreamException */ private Object readResolve() throws ObjectStreamException { return s; } }
2.懒汉式单例模式。
package com.zby.pattern; import java.io.ObjectStreamException; import java.io.Serializable; /** * * <class description> 懒汉式单例模式。优点:只有在真正使用的时候才回去实例化对象,避免浪费资源。 * 缺点:需要将获取实例的方法同步,否则会出现线程安全问题,但是每次获取实例都进行同步 ,降低效率。 * * @author: zby * @version: 1.0, 2017年6月22日 */ public class Singleton02 implements Serializable { private static final long serialVersionUID = 1L; // 私有化静态实例 private static Singleton02 s; // 私有化构造方法 private Singleton02() { // 避免反射破坏单例 if (null != s) { throw new RuntimeException("No,you can't do this!"); } } // 提供全局访问点,需要进行同步 public static synchronized Singleton02 getInstance() { if (null == s) { // 第一次获取实例的时候实例化对象 s = new Singleton02(); } return s; } /** * * <method description>防止对象反序列化时破坏单例 * * @return * @throws ObjectStreamException */ private Object readResolve() throws ObjectStreamException { return s; } }
3.双重检测锁单例模式。
package com.zby.pattern; import java.io.ObjectStreamException; import java.io.Serializable; /** * * <class description> 双重检测锁单例模式 * 优点:延迟加载,而且只会在创建时同步。缺点:由于编译器优化和JVM底层内部模型,偶尔会出问题,不建议使用 * * @author: zby * @version: 1.0, 2017年6月22日 */ public class Singleton03 implements Serializable { private static final long serialVersionUID = 1L; // 私有化静态实例 private static Singleton03 s; // 私有化构造方法 private Singleton03() { // 避免反射破坏单例 if (null != s) { throw new RuntimeException("No,you can't do this!"); } } // 提供全局访问点,只有初始化时需要进行同步 public static Singleton03 getInstance() { if (null == s) { Singleton03 singleton03; synchronized (Singleton03.class) { singleton03 = s; if (null == singleton03) { synchronized (Singleton03.class) { if (null == singleton03) { singleton03 = new Singleton03(); } } s = singleton03; } } } return s; } /** * * <method description>防止对象反序列化时破坏单例 * * @return * @throws ObjectStreamException */ private Object readResolve() throws ObjectStreamException { return s; } }
4.静态内部类单例模式。
package com.zby.pattern; import java.io.ObjectStreamException; import java.io.Serializable; /** * * <class description> 静态内部类单例模式 优点:线程安全,延迟加载。 * 静态内部类在外部类加载的时候不会被加载,而是在用到的时候才会被加载,所以可以延迟加载。 * @author: zby * @version: 1.0, 2017年6月22日 */ public class Singleton04 implements Serializable { private static final long serialVersionUID = 1L; // 私有化构造方法 private Singleton04() { // 避免反射破坏单例 if (null != SingletonClassInstance.s) { throw new RuntimeException("No,you can't do this!"); } } // 静态内部类,初始化静态实例对象 private static class SingletonClassInstance { private static final Singleton04 s = new Singleton04(); } public static Singleton04 getInstance() { return SingletonClassInstance.s; } /** * * <method description>防止对象反序列化时破坏单例 * * @return * @throws ObjectStreamException */ private Object readResolve() throws ObjectStreamException { return SingletonClassInstance.s; } }
5.枚举单例模式。
package com.zby.pattern; import java.io.ObjectStreamException; import java.io.Serializable; /** * * <class description> 枚举单例模式 优点:从JVM根本上保证单例,避免反射和反序列化破坏。缺点:不能延迟加载。 * 可以参考枚举父类的源码:java.lang.Enum<E> * @author: zby * @version: 1.0, 2017年6月22日 */ public enum Singleton05 { INSTANCE; }
总结:
效率:看代码就能看出进行同步的效率肯定低于非同步的。
推荐文章:http://blog.csdn.net/li295214001/article/details/48135939/