单例模式

1、场景类

//单例模式-场景类
public class SingletonClient {

    public static void test() {
        ISingleton iSingleton=Singleton05.getInstance();
        iSingleton.doSomeThing();
    }
}

2、接口

//其实没啥卵用,只是为了测试方便加的
public interface ISingleton {
    void doSomeThing();
}

3、几种不同的单例模式

1.饿汉式
2.懒汉式
3.双重锁定式
4.静态内部类式
5.枚举式

1.饿汉式-占内存,用空间换时间

public class Singleton01 implements ISingleton {
    private static Singleton01 instance = new Singleton01();

    /**
     * 禁止外部创建
     */
    private Singleton01() {
    }

    public static Singleton01 getInstance() {
        return instance;
    }

    @Override
    public void doSomeThing() {
        LogUtil.e("我在做事……");
    }
 }

2.懒汉式-每次都要同步,浪费时间

public class Singleton02 implements ISingleton {
    private static Singleton02 instance ;

    /**
     * 禁止外部创建
     */
    private Singleton02() {
    }

    public static synchronized Singleton02 getInstance() {
        if(instance==null){
            instance=new Singleton02();
        }
        return instance;
    }

    @Override
    public void doSomeThing() {
        LogUtil.e("我在做事……");
    }
}

3.双重锁定式-会遇到DCL失效

public class Singleton03 implements ISingleton {
    private static Singleton03 instance;

    /**
     * 禁止外部创建
     */
    private Singleton03() {
    }

    public static Singleton03 getInstance() {
        //第一层避免不必要的线程同步
        if (instance == null) {
            synchronized (Singleton03.class) {
                //第二层为空则创建实例
                if (instance == null) {
                    instance = new Singleton03();
                }
            }
        }
        return instance;
    }

    @Override
    public void doSomeThing() {
        LogUtil.e("我在做事……");
    }
}

什么的DCL失效?

new Instance()到底发生了什么?
memory = allocate(); //1:分配对象的内存空间
ctorInstance(memory); //2:初始化对象
instance = memory; //3:设置instance指向刚分配的内存地址
上面的伪代码中2、3步可能重排。

DCL失效的解决方案:

Java5以后的版本,可以利用volatile关键字。
Why?
在java5以前,volatile原语不怎么强大,只能保证对象的可见性
但在java5之后,volatile语义加强了,被volatile修饰的对象,将禁止该对象上的读写指令重排序
这样,就保证了线程B读对象时,已经初始化完全了

4.静态内部类式-反序列化会重建实例

public class Singleton04 implements ISingleton {
    private static Singleton04 instance ;

    /**
     * 禁止外部创建
     */
    private Singleton04() {
    }

    public static Singleton04 getInstance() {
        return SingletonHolder.instance;
    }

    public static class SingletonHolder{
        private static final Singleton04 instance=new Singleton04();
    }

    @Override
    public void doSomeThing() {
        LogUtil.e("我在做事……");
    }
}

5.枚举式-暂无缺点,不过也比较占内存吧

public enum Singleton05 implements ISingleton {
    INSTANCE;

    /**
     * 禁止外部创建
     */
    private Singleton05() {
    }

    public static Singleton05 getInstance() {
        return INSTANCE;
    }

    @Override
    public void doSomeThing() {
        LogUtil.e("我在做事……");
    }
}
2016-10-29 10:3511