单例模式

一.简介

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。

单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例

简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例。

二.为什么要用单例模式?

  1. 防止一个要全局使用的类频繁创建和销毁 ,节省内存,节省计算
  2. 防止多个实例造成结果混乱
  3. 方便管理,例如有些工具类我们只需要一个实例

三.要求

要求:只需要三部分即可保证只有一个实例

  1. 不允许被外部类 new 对象
  2. 在本类中创建对象
  3. 对外提供接口调用创建好的对象

四.实现思路

  1. 构造方法私有化
  2. 在本类中 new 一个本类对象
  3. 创建一个 public 方法返回上步创建好的对象以供外部调用

五.单例模式的码实现

一般来说,单例模式使用饿汉式实现就可以 饿汉式写法 和 静态内部类写法 就可以

懒汉: 要用时再去创建
饿汉: 类加载时化就去创建

5.1 懒汉式,线程不安全

 * 是否 Lazy 初始化:是
 * 是否多线程安全:否
 * 优点:第一次调用才初始化,避免内存浪费。
 * 描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
  这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。
public class SingletonPattern {

    //让构造函数为 private,这样该类就不会被实例化
    private SingletonPattern() {
    }

    //创建 SingletonPattern 的一个对象
    private static SingletonPattern instance;


    //获取唯一可用的对象
    public static SingletonPattern getInstance() {
        if (instance == null) {
            instance = new SingletonPattern();
        }
        return instance;
    }
}

5.2 懒汉式,线程安全

 * 是否 Lazy 初始化:是
 * 是否多线程安全:是
 * 描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
 * 优点:第一次调用才初始化,避免内存浪费。
 * 缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。效率低
public class SingletonPattern {

    //让构造函数为 private,这样该类就不会被实例化
    private SingletonPattern() {
    }

    //创建 SingletonPattern 的一个对象,加上synchronized关键字,加上锁,保证单例,不过会影响效率,要是性能要求不高,就可以用这个方法
    private static SingletonPattern instance;

    //获取唯一可用的对象
    public static synchronized SingletonPattern getInstance() {
        if (instance == null) {
            instance = new SingletonPattern();
        }
        return instance;
    }
}

5.3 双检锁/双重校验锁(DCL,即 double-checked locking)

 * JDK 版本:JDK1.5 起
 * 是否 Lazy 初始化:是
 * 是否多线程安全:是
 * 效率高,线程安全
 * 描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
public class SingletonPattern {

    //加上volatile就是为了防止产生指令的重排序问题
    private volatile static SingletonPattern singleton;

    //让构造函数为 private,这样该类就不会被实例化
    private SingletonPattern() {
    }

    //获取唯一可用的对象
    public static SingletonPattern getSingleton() {
        if (singleton == null) {//第一次检查
            synchronized (SingletonPattern.class) {//加锁
                if (singleton == null) {//第二次检查
                    singleton = new SingletonPattern();
                }
            }
        }
        return singleton;
    }
}

5.4 静态内部类

 * 是否 Lazy 初始化:是
 * 是否多线程安全:是
 * 描述:这种方式能达到双检锁方式一样的功效,但实现更简单。
 * 线程安全
public class SingletonPattern {

    //静态内部类
    private static class SingletonHolder {
        private static final SingletonPattern singletonPattern = new SingletonPattern();
    }

    //让构造函数为 private,这样该类就不会被实例化
    private SingletonPattern (){}

    //获取唯一可用的对象
    public static final SingletonPattern getInstance() {
        return SingletonHolder.singletonPattern;
    }
}

5.5 枚举

 * JDK 版本:JDK1.5 起
 * 是否 Lazy 初始化:否
 * 是否多线程安全:是
 * 描述:这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
    public enum SingletonPattern {
        INSTANCE;
        public void whateverMethod() {
        }
    }

5.6 饿汉式,线程安全

 * 是否 Lazy 初始化:否
 * 是否多线程安全:是
 * 描述:这种方式比较常用,但容易产生垃圾对象。
 * 优点:没有加锁,执行效率会提高。线程安全
 * 缺点:类加载时就初始化,浪费内存。
public class SingletonPattern {
    //类加载时就完成了实例化SingletonPattern
    private static SingletonPattern instance = new SingletonPattern();

    //让构造函数为 private,这样该类就不会被实例化
    private SingletonPattern (){}

    //获取唯一可用的对象
    public static SingletonPattern getInstance() {
        return instance;
    }
}    

5.7 饿汉式,线程安全 (静态代码块形式)

public class SingletonPattern {
    //Singleton对象属性
    private static SingletonPattern singletonPattern;

    //类加载时的时候初始化赋值
    static {
        singletonPattern = new SingletonPattern();
    }

    //获取唯一可用的对象
    public static SingletonPattern getInstance() {
        return singletonPattern;
    }
}    

一般来说,单例模式使用饿汉式实现就可以 饿汉式写法 和 静态内部类写法 就可以

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘德华一不小心就打代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值