单例模式-讲解

2019-10-24  本文已影响0人  cao苗子

什么是单列模式?
百度百科:单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)。

1.懒汉式

/**
 * created by panshimu
 * on 2019/10/24
 *  懒汉式-单列模式
 */
public class Single01 {
    public static Single01 mSingle01;
    private Single01(){
    }
    /**
     * 存在多线程并发问题 可能会存在多个实列
     * @return
     */
    public static Single01 getInstance(){
        if(mSingle01 == null){
            mSingle01 = new Single01();
        }
        return mSingle01;
    }
}

2.饿汉式

/**
 * created by panshimu
 * on 2019/10/24
 * 饿汉式-单列模式
 */
public class Single02 {
    //随着类的加载就创建对象
    public static Single02 mSingle02 = new Single02();
    private Single02(){
    }
    public static Single02 getInstance(){
        return mSingle02;
    }
}

3.线程安全

/**
 * created by panshimu
 * on 2019/10/24
 */
public class Single05 {
    public static Single05 mSingle05;
    private Single05(){
    }

    /**
     * 加同步锁 能解决同步问题 但是会影响效率 因为每一次都要加锁的判断
     * @return
     */
    public static synchronized Single05 getInstance(){
        if(mSingle05 == null){
            mSingle05 = new Single05();
        }
        return mSingle05;
    }
}

4.线程和效率

/**
 * created by panshimu
 * on 2019/10/24
 */
public class Single06 {

    //防止重排序 线程可见
    public static volatile Single06 mSingle06;
    private Single06(){
    }

    /**
     * 既保证线程安全 效率也还是比较高的
     * @return
     */
    public static Single06 getInstance(){
        if(mSingle06 == null){
            synchronized (Single06.class){
                if(mSingle06 == null){
                    mSingle06 = new Single06();
                }
            }
        }
        return mSingle06;
    }
}

第四种 单列模式中 既保证了线程的安全 又提高了效率,但是还是存在问题的。
比如 线程的不可性,重排序问题。在多线程的情况下。

线程的可见行:某一个线程中改变了某一个公共对象或是公共变量,短时间内可能会存在在某一个线程是不可见的,意思就是在某一个线程中这个值可以还是原来的值。因为每一个线程都有自己的缓存区。

看下面的列子:

public static void main(String[] args){
        VolatileThread volatileThread = new VolatileThread();
        new Thread(volatileThread).start();
        while (true){
            if(volatileThread.isFlag()){
                System.out.println("00000000000000000000");
                break;
            }
        }
    }
    static class VolatileThread implements Runnable{
        private boolean flag = false;
        @Override
        public void run() {
            try{
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            flag = true;
            System.out.println("flag="+flag);
        }
        public boolean isFlag(){
            return flag;
        }
    }

执行上面的列子,发现 System.out.println("00000000000000000000"); 并没有执行,实际上 flag=true 了。但是 volatileThread.isFlag() 返回的还是 false 所以说短时间内 值还没有被改变。
怎么解决这个问题呢?
只需要给 flag 变量加上 volatile 关键字 就可以了。

在4中把改为

 public static volatile Single05 mSingle05;

就可以了。

5.静态内部类

保证线程的安全 用到的时候才会new

/**
 * created by panshimu
 * on 2019/10/24
 * 静态内部类
 */
public class Single04 {
    private Single04(){
    }
    public static Single04 getInstance(){
        return Single04Holder.mSingle04;
    }
    public static class Single04Holder{
        private static volatile Single04 mSingle04 = new Single04();
    }
}

6.容器管理

/**
 * created by panshimu
 * on 2019/10/24
 *  容器管理
 */
public class Single07 {
    private static Map<String,Object> mSingleMap = new HashMap<>();
    private Single07(){
    }
    static {
        mSingleMap.put("miaozi",new Single07());
    }

    public static Object getInstance(String str){
        return mSingleMap.get(str);
    }
}

好了 ,单列模式就到这里啦。

上一篇 下一篇

猜你喜欢

热点阅读