单例设计模式singleton

简单引入

单例设计模式作为最简单,最常用的设计模式。一般是这两中写法,这两种写法教科书所谓的标准写法,但是实际上存在不少问题。后面介绍标准写法,以规避这些问题。

1.懒汉式:


/**
     * 问题在于,当多线程工作的时候,如果有多个线程同时运行到if (instance ==
     * null),都判断为null,那么两个线程就各自会创建一个实例——这样一来,就不是单例了。
     */
class Singleton {

    private Singleton() {
    };

    private static Singleton s;

    public static Singleton getInstance() {
        if (s == null) {
            s = new Singleton();
        }
        return s;
    }

}

2.恶汉式

class Singleton {
    private Singleton() {
    }

    private static Singleton singleton = new Singleton();

    public static Singleton getInstance() {
        return singleton;
    }

}

标准写法

改变懒汉式1.

(规避线程安全问题)加上 synchronized修饰方法即可

class Singleton {

    private Singleton() {
    };

    private static Singleton s;

    public static synchronized Singleton getInstance() {
        if (s == null) {
            s = new Singleton();
        }
        return s;
    }

}

改变懒汉式2. 双重检查 Double-Check』写法

1.第一个if 只有instance为null的时候,才进入synchronized的代码段——大大减少了几率。
2.第二个if 是为了防止可能出现多个实例的情况。

 class DoubleCheck {

    private DoubleCheck() {
    }

    private static DoubleCheck dCheck;

    public static DoubleCheck getInstance() {
        if (dCheck == null) {
            synchronized (DoubleCheck.class) {
                if (dCheck == null) {
                    dCheck = new DoubleCheck();
                }
            }
        }
        return dCheck;
    }

}

改变懒汉式2.之终极版 防止指令重排列 volatile

不知道原子操作,与指令重排的建议复习下

 class DoubleCheck2 {
    private DoubleCheck2() {
    }

    private static volatile DoubleCheck2 sCheck;

    public static DoubleCheck2 getInstance() {
        if (sCheck == null) {
            synchronized (DoubleCheck2.class) {
                if (sCheck == null) {
                    sCheck = new DoubleCheck2();
                }
            }
        }
        return sCheck;
    }

}

1.恶汉式:

说白了,有classloder装载 就是一开始就创建类

/*
     * 缺点也就只是饿汉式单例本身的缺点所在了——由于INSTANCE的初始化是在类加载时进行的,而类的加载是由ClassLoader来做的,
     * 所以开发者本来对于它初始化的时机就很难去准确把握:
     * 
     * 可能由于初始化的太早,造成资源的浪费 如果初始化本身依赖于一些其他数据,那么也就很难保证其他数据会在它初始化之前准备好。
     */
class Singleton {
    private Singleton() {
    }

    private static final Singleton singleton = new Singleton();

    public static Singleton getInstance() {
        return singleton;
    }

}

由于静态内部类实现

class innerSingleton {
    private innerSingleton() {

    }

    private static class SingletonHolder {
        private static final innerSingleton SINGLETON = new innerSingleton();
    }

    public static innerSingleton getInstance() {
        return SingletonHolder.SINGLETON;
    }

}

猜你喜欢

转载自www.cnblogs.com/dgwblog/p/9114189.html