设计模式之单例模式(Singleton)

1. 什么是单例模式?

确保一个类只有一个实例,并提供一个全局访问点

单例模式见名知意, 就是只有一个实例。在整个系统应用中不管获取多少次,拿到的都是同一个对象, 这就是单例模式。

2. 单例模式用来干什么,什么时候使用?

我们知道了单例模式的意思, 那么为什么要用这个单例模式呢?
答案很简单,在需要重复创建和销毁对象的时候使用单例模式,可以节省系统资源,比如工具类、DAO等这种在多个地方使用却只需要一个实例就可以完成操作的类,我们就可以把它设计为单例模式。

3. 怎么实现单例模式?

  • 饿汉式

饿汉式,启动时就初始化完毕,不存在线程安全问题,实例不使用会消耗资源

package com.single.hungry;

public class Hungry {

    private final static Hungry hunger = new Hungry();

    private Hungry() {
    }

    public static Hungry getInstance() {
        return hunger;
    }
}
  • 懒汉式

第一版:使用时初始化,但是无法保证线程安全,有可能两个线程同时进入到 if (null == lazyOne)判断里面,然后初始化两次。

package com.single.lazy;

public class LazyOne {

    private static LazyOne lazyOne;

    private LazyOne() {
        System.out.println("init");
    }

    public static LazyOne getInstance() throws InterruptedException {
        if (null == lazyOne) {
            Thread.sleep(1000);
            lazyOne = new LazyOne();
        }
        return lazyOne;
    }

}

第二版:使用synchronized关键字,线程安全,每次访问都会加锁,效率不高

package com.single.lazy;

public class LazyTwo {

    private static LazyTwo lazyTwo;

    private LazyTwo() {
        System.err.println("init");
    }

    public static synchronized LazyTwo getInstance() throws InterruptedException {
        if (null == lazyTwo) {
            lazyTwo = new LazyTwo();
        }
        return lazyTwo;
    }

}

第三版:双重锁,线程安全

package com.single.lazy;

public class LazyFour {

    private LazyFour(){
        System.err.println("init");
    }

    //一个线程中对该变量的修改对其他线程可见
    public volatile static LazyFour lazyFour = null;

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

第四版:静态内部类实现,当调用LazyThree时,才会去初始化LazyHolder.LazyThree .lazy实例。

package com.single.lazy;

public class LazyThree {

    private LazyThree() {
        System.err.println("init");
    }

    public static final LazyThree getInstance() {
        return LazyHolder.lazy;
    }

    public static class LazyHolder {
        private static final LazyThree lazy = new LazyThree();
    }

}

最后还有什么注册式单例(Spring中使用)、枚举单例就不贴代码了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容