饿汉模式
public class Sigleton { //饿汉模式 outInstance是私有的 private static Sigleton ourInstance = new Sigleton(); /** * 此实现是线程安全的 JVM在加载此类时,因为对于static属性的初始化只能由一个线程执行且仅执行一次 * 缺点:instance在类装载时就实例化 这时候初始化instance显然没有达到lazy loading的效果 * @return */ public static Sigleton getInstance() { return ourInstance; } //把构造函数声明为private 客户对象无法创建该实例 private Sigleton() { } }懒汉模式
public class Sigleton2 { //懒汉模式(需要时才实例化对象) private static Sigleton2 instance; /** * 线程不安全 原因:getInstance在高并发环境下可能会被同时调用,导致if(instance==null)判断就不靠谱 * @return */ // public static Sigleton2 getInstance() { // if (instance == null) { // instance = new Sigleton2(); // } // return instance; // } /** * 解决方法:添加synchornized关键字 * 缺点:性能降低 * @return */ public static synchronized Sigleton2 getInstance() { if (instance == null) { instance = new Sigleton2(); } return instance; } private Sigleton2(){ } }双重校验锁
public class DoubleCheckSingleton { //此方法需要在Java 5及以上的版本才能运行 volatile关键字在Java5引入 public volatile static DoubleCheckSingleton instance = null; private DoubleCheckSingleton(){} public static DoubleCheckSingleton getInstance() { if (instance == null) { //检查实例是否创建 如果没有把 DoubleCheckSingleton.class设置为同步 synchronized (DoubleCheckSingleton.class) { if (instance == null) { //double check instance = new DoubleCheckSingleton(); } } } return instance; } }静态内部类
public class StaticSingleton { private static class SingletonHolder { private static final StaticSingleton INSTANCE = new StaticSingleton(); } private StaticSingleton (){} //这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程 public static final StaticSingleton getInstance() { return SingletonHolder.INSTANCE; } }Singleton的序列化
如果单例类实现了Serializable接口,默认情况下,每次反序列化总会创建一个新的实例对象。 解决方法:重写readResolve()方法,直接返回单例对象
package Sigleton; import java.io.Serializable; /** * Created by Zz on 2017/5/3 0003. */ public class Sigleton implements Serializable{ private static final long serialVersionUid = -6012841243252L; //饿汉模式 outInstance是私有的 private static Sigleton ourInstance = new Sigleton(); /** * 此实现是线程安全的 JVM在加载此类时,因为对于static属性的初始化只能由一个线程执行且仅执行一次 * 缺点:instance在类装载时就实例化 这时候初始化instance显然没有达到lazy loading的效果 * @return */ public static Sigleton getInstance() { return ourInstance; } //把构造函数声明为private 客户对象无法创建该实例 private Sigleton() { } private Object readResolve(){ return ourInstance; } }