继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

单例模式

牧码
关注TA
已关注
手记 9
粉丝 1
获赞 5

单例模式

定义

确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例(以静态方法)

应用

  • 整个项目中需要一个共享访问点或者共享数据
  • 创建一个对象需要消耗的资源过多,如要访问IO和数据库资源等
  • 需要定义大量静态常量和静态方法的环境

优点

  • <font color=#2a3342>减少内存开支</font>
    在内存中只有一个实例,减少对象频繁创建和销毁的性能开销
  • <font color=#2a3342>避免对资源多重占用</font>
    由于只有一个实例存在,避免对同一资源文件的同时操作

单例模式<font color=#3480d7>6</font>种实现

1. 饿汉模式

public class Singleton {
    // 第一次加载到内存中就会被初始化,不管需不需要都给一个实例
    // 所以创建实例本身是线程安全的
    private static final Singleton instance = new Singleton();
    // 构造函数
    private Singleton() {
    }
    // 静态方法获取实例
    public static Singleton getInstance() {
        return instance;
    }
}

2. 懒汉模式

public class Singleton {
    // 一开始不新建实例,需要时再创建
    private static Singleton instance = null;

    private Singleton() {
    }
    // 线程不安全,多个线程调用该方法时还有可能产生多个实例
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

3. 线程安全的懒汉模式

public class Singleton {
    private static Singleton instance = null;

    private Singleton() {
    }

    // 添加关键字synchronized
    // 同一时刻最多只有一个线程调用该方法,结果效率不是很好
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

4. 双重检验锁

public class Singleton {
    // JDK1.5或之后版本添加关键字volatile,防止编译器自行优化代码
    private /**volatile**/ static Singleton instance = null;

    private Singleton() {
    }

    public static Singleton getInstance() {
        // 第一重检验锁,如果不为空直接返回实例
        if (instance == null) {
            synchronized (Singleton.class) {
                // 第二重检验锁,因为可能有多个线程进入
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

5. 静态内部类

public class Singleton {
    // 线程安全,饿汉式静态内部类
    // 就算Singleton类被装载了,instance不一定被初始化,因为Inner类没有被主动使用
    private static class SingletonInner {
        private static final Singleton INSTANCE = new Singleton();
    }

    private Singleton() {

    }

    public static Singleton getInstance() {
        return SingletonInner.INSTANCE;
    }
}

6. 枚举

/**
 * 通过Singleton.INSTANCE来访问实例对象
 * 而且创建枚举默认就是线程安全的,还可以防止反序列化带来的问题
 */
public enum Singleton{
    // 实际上做了
    /**new Enum<Singleton>("INSTANCE", 0)**/
    INSTANCE;
    // 其他方法
}
打开App,阅读手记
2人推荐
发表评论
随时随地看视频慕课网APP