单例模式 Singleton

单例模式

一. 概述

  • 在GoF一书中设计模式如下分类
    • 创建模式(Creational Patterns)
      • Singleton 单例模式
      • Factory Method
      • Abstract Factory
      • Builder
      • Prototype
    • 结构模式(Structural Patterns)
      • Adapter
      • Bridge
      • Composite
      • Decorator
      • Facade
      • Flyweight
      • Proxy
    • 行为模式(Behavioral Patterns)
      • Chain of Responsibility
      • Command
      • Interpreter
      • Iterator
      • Mediator
      • Memento
      • Observer
      • State
      • Strategy
      • Template Method
      • Visitor

二. 单例模式介绍

  • Singleton模式的意图是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
  • Singleton模式下,每个应用程序中的每个对象都使用Singleton类的同一实例,在一个协作对象对Singleton类所作的修改对于另一个协作对象是可见的。
  • Singleton模式需要注意如下两点:
    • 为了确保类不被构造函数实例化,需要将类的构造函数定义为保护或者私有的。
    • 对外提供一个特殊方法,调用这个方法的时候,检查对象是否已经实例化。如果已经实例化,该方法仅返回对象的一个引用。如果尚未实例化,该方法实例化该对象并返回对此新实例的一个引用。

三. 单例模式的实现

1. 懒汉式 (线程不安全)
class Singleton{

  private Singleton() {}

  private static Singleton instance;

  public static Singleton getInstance(){
    if(instance==null){
      instance = new Singleton();
    }
    return  instance;
  }
  
}
  • 单例模式不允许外部实例化,所以我们将构造函数标记为私有 private Singleton() {}
  • 此种方式虽然满足了懒加载,但是对于多线程,依旧会造成多实例并存的现象。
2. 懒汉式 (线程安全)
class Singleton{

    private Singleton() {}

    private static Singleton instance;

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

}
  • 此种方式与上述方式唯一不同的地方是给方法上了锁,添加了synchronized关键字。
  • 此种方式实现了线程安全,但是每次访问的时候不论对象是否已经实例化过,都需要使用锁,占用资源,影响性能,所以不建议使用此种方式实现单例模式
3. 饿汉式 - 静态变量初始化 (线程安全)
class Singleton{

    private Singleton() {}

    private final  static Singleton instance = new Singleton();

    public static Singleton getInstance(){
        return  instance;
    }

}
  • 在类加载的时候Singleton类就直接初始化了,此种方式是线程安全的,但并不是懒加载,无论我们程序中是否用到此类都会被创建。
4. 饿汉式 - 静态代码块初始化 (线程安全)
class Singleton{

    private Singleton() {}

    private final  static Singleton instance ;

    static {
        instance = new Singleton();
    }

    public static Singleton getInstance(){
        return  instance;
    }

}
  • 此种方式与上述方式基本相同,静态代码块中的代码在类加载的时候也一并执行。此种方式是线程安全的,但并不是懒加载,无论我们程序中是否用到此类都会被创建。
5. 双重锁校验 (线程安全)
class Singleton{

    private Singleton() {}

    private static volatile  Singleton instance;

    public static Singleton getInstance(){
        if(instance!=null){
            return  instance;
        }
        synchronized (Singleton.class){
            if(null==instance){
                instance = new Singleton();
            }
        }
        return  instance;
    }

}
  • 双重锁校验(Double-Checked Locking)模式是方法级别加锁(synchronized)的优化,拥有懒加载的特性,同时也保证了线程安全性。
6. 静态内部类方式 (线程安全)
class Singleton{
    
    private Singleton() {}

    private static class  SingletonHolder{
        private static Singleton instance = new Singleton();
    }

    public static Singleton getInstance(){
        return  SingletonHolder.instance;
    }
}
  • 使用静态内部类的方式,既保证了懒加载又保证了线程安全,当调用getInstance()时,才会加载 Singleton 实例。
  • JVM虚拟机在加载类时候,保证了多线程的安全性,这种方式也是比较推荐的一种方式
7. 使用枚举解决单例问题 (线程安全)
enum Singleton{
    INSTANCE;
    public void test(){
        System.out.println("hi~");
    }
}
  • Effective Java作者推荐的解决方式,这种方式保证了线程安全,单一实例。

四. 单例模式的应用

  • 在JDK源码中 Runtime 使用了单例模式,如下:
public class Runtime {
  private static final Runtime currentRuntime = new Runtime();

  public static Runtime getRuntime() {
    return currentRuntime;
  }

  private Runtime() {
  }
}

每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。例如获取 Java 虚拟机中的空闲内存量、总内存量、处理器内核数量等等。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值