设计模式

设计模式5:单例模式(Singleton)

2019-04-23  本文已影响0人  ygxing

1. 简介

单例模式是创建模式中的一种
是一个非常简单的设计模式,
类中只有一个实例,
某些对单例模式的扩展用法中,一个类中会存在多个实例
1.1优点:
- 运行内存中只有固定个数的实例,占用资源少
- 不需要重复实例化和销毁,提高系统性能
1.2缺点:
- 线程不安全,不适用于被频繁修改的对象
- 不方便扩展
1.3使用场景
- 共享的资源: 例如日志,文件等等
- 通用的方法: 例如JSON序列化,加密解密等等

2.实现方式

整体上分为两种
- 饿汉模式: 在类初始化的过程中,就实例化了单例对象,
- 懒汉模式: 在需要使用到单例对象的时候,去实例化单例对象
2.1 饿汉模式
在类进行初始化的过程中,就实例化了单例对象,
可以确保整个内存中只有固定个数对象
public class YanggxSingleton {

    /**
     * 单例对象
     */
    public static final YanggxSingleton instance = new YanggxSingleton();
    
    //私有的构造函数,防止被实例化
    private YanggxSingleton() {}
}
2.2 懒汉模式
在需要使用到单例对象的时候,才会实例化对象
有以下几种加载方式
2.2.1 不加锁
线程不安全
在进行instance == null判断的时候,
可能会有多个线程同时返回true,
从而导致多次实例化
public class YanggxSingleton {
    // 单例对象
    private static YanggxSingleton instance;
    // 私有的构造函数,防止被实例化
    private YanggxSingleton() {}

    /**
     * 获取单例对象
     * @return
     */
    public static YanggxSingleton getInstance() {
        if (instance == null) {            
            instance = new YanggxSingleton();
        }
        return instance;
    }
}
2.2.2 方法上加锁
- 可以确保线程安全
- synchronized锁住了整个方法,执行效率低
public class YanggxSingleton {

    // 单例对象
    private static YanggxSingleton instance;

    // 私有的构造函数,防止被实例化
    private YanggxSingleton() {}

    /**
     * 获取单例对象
     * @return
     */
    public static synchronized YanggxSingleton getInstance() {
        if (instance == null) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance = new YanggxSingleton();
        }
        return instance;
    }
}
2.2.3 双重检查锁
既可以确保线程安全,保证内存中只有一个实例,
又可以保证系统性能,提高运行效率
public class YanggxSingleton {

    // 单例对象
    private static YanggxSingleton instance;

    // 私有的构造函数,防止被实例化
    private YanggxSingleton() {}

    /**
     * 获取单例对象
     * @return
     */
    public static synchronized YanggxSingleton getInstance() {
        //双重检查
        if (instance == null) {
            synchronized (YanggxSingleton.class) {
                //锁住class对象之后
                //这里就只有一个线程访问到
                //因为instance可能已经被其他线程实例化了
                //所以再次判断instance是否为空
                //防止多次实例化
                if (instance == null) {
                    instance = new YanggxSingleton();
                }
            }
        }
        return instance;
    }
}
上一篇下一篇

猜你喜欢

热点阅读