美文网首页
Java学习笔记--单例

Java学习笔记--单例

作者: Allens_Lee | 来源:发表于2019-12-12 13:11 被阅读0次

一、什么是单例模式?

单例模式(Singleton Pattern),顾名思义,就是被单例的对象只能有一个实例存在。单例模式的实现方式是,一个类能返回对象的一个引用(永远是同一个)和一个获得该唯一实例的方法(必须是静态方法)。通过单例模式,我们可以保证系统中只有一个实例,从而在某些特定的场合下达到节约或者控制系统资源的目的。

二、代码如何实现?

  1. 饿汉模式
    最常见、最简单的单例模式写法之一,即在类的一开始就给它新建一个实例。示例如下:
//饿汉模式
class Singleton {
    
    //一开始就创建一个实例
    private static Singleton instance = new Singleton();
    
    private Singleton() { }
    
    //获取实例
    public static Singleton getInstance() {
        return instance;
    }
}

存在的问题:这种方式有一个明显的缺点,那就是不管有没有调用过获得实例的方法,每次都会新建一个实例。

  1. 懒汉模式
    饿汉模式的升级版本,即在类的一开始只创建一个引用,但并不实例化,只有在需要使用到它的时候,先去判断实例是否为空,如果为空的时候才会新建一个实例来使用。示例如下:
//懒汉模式
class Singleton {

    //一开始并不创建实例
    private static Singleton instance;

    private Singleton() { }

    //需要时再新建
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

存在的问题:该种模式存在一个严重的问题。那就是如果有多个线程并行调用getInstance()的时候,还是会创建多个实例的,单例模式就失效了。

  1. 线程安全的懒汉模式
    在懒汉模式的基础上,把它设为线程同步(synchronized)就好了。synchronize的作用就是保证在同一时刻最多只有一个线程运行,这样就避免了多线程带来的问题。示例代码如下:
//懒汉模式(线程安全)
class Singleton {
    
    private static Singleton instance;

    private Singleton() { }

    //添加了 synchronized 关键字
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

存在的问题:这种模式看似很好的解决了多线程的问题,但是它的效率并不高,每次调用获得实例的方法时都要进行同步,但是多数情况下并不需要同步操作。

  1. 双重检验锁
    为了解决第三种模式的问题,延伸出来双重检验锁模式,即在获取实例的方法中,先去判断该实例是否为空,如果为空在再加同步锁,然后新建实例。示例如下:
//双重检验锁
class Singleton {

    private static Singleton instance;

    private Singleton() { }
    
    public static Singleton getInstance() {
        //第一个检验锁,如果不为空直接返回实例对象,为空才进入下一步
        if (instance == null) {
            //第二个检验锁,因为可能有多个线程进入到if语句内,所以加线程同步锁
            synchronized (Singleton.class) { 
                instance = new Singleton();   
            }
        }
        return instance;
    }
}

存在的问题:该种模式此时并不是完美的。主要问题在在于instance = new Singleton();这句代码,因为JVM(Java虚拟机)执行这句代码的时候,要做好几件事情,而JVM为了优化代码,有可能造成做这几件事情的执行顺序是不固定的,从而造成错误。

解决办法:为了解决上述问题,我们需要给实例加一个volatile关键字,它的作用就是防止编译器自行优化代码。此时,双重检验锁模式才完美实现。

private volatile static Singleton instance;
  1. 静态内部类
    这种方式,利用了 JVM 自身的机制来保证线程安全,因为 SingletonHolder 类是私有的,除了 getInstance() 之外没有其它方式可以访问实例对象,而且只有在调用 getInstance() 时才会去真正创建实例对象。示例如下:
//静态内部类
class Singleton {

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

    public static Singleton getInstance() {
        return SingletonHolder.singleton;
    }
}
  1. 枚举
    我们可以通过 Wife.INSTANCE 来访问实例对象,而且创建枚举默认就是线程安全的,还可以防止反序列化带来的问题。最为推荐。示例如下:
//利用枚举的方式创建单例
public enum Singleton {
    INSTANCE;

    public void whateverMethod() {
        
    }
}

相关文章

  • 【Java】设计模式 —— 深入浅出单例模式

    学习笔记 参考:深入浅出单实例SINGLETON设计模式单例模式【Java】设计模式:深入理解单例模式 场景:一般...

  • Java学习笔记--单例

    一、什么是单例模式? 单例模式(Singleton Pattern),顾名思义,就是被单例的对象只能有一个实例存在...

  • Java单例模式学习笔记

    单例模式:一个类只能创建一个实例,并提供一个全局访问点。常用的有:饿汉式、懒汉式。 饿汉式(线程安全,调用效率高,...

  • 初识设计模式之单例模式

    此文为笔者个人的学习笔记,在学习部分博客、书籍、资料后所总结,仅供参考。 对单例模式的认识单例模式是什么单例模式的...

  • 2020-11-02-Spring单例 vs. 单例模式

    Spring 单例不是 Java 单例。本文讨论 Spring 的单例与单例模式的区别。 前言 单例是 Sprin...

  • JAVA学习笔记之单例模式

    如何实现单例设计模式。 需求:类在内存中的对象只有一个。 分析:A:让外界不能去创建对象。把构造方法私有化。B:类...

  • Java中单例模式你用的哪一种?

    一起讨论java中的单例模式。单例模式是java设计模式中算是最简单的设计模式了。 * java实现单例模式的写法...

  • JAVA学习笔记(三)

    前言: 这周忙的不行,没学多少东西,就简单的学习下Java的单例吧。 设计模式之单例 单例模式是最简单也是最常用的...

  • JAVA中各种单例模式的实现与分析

    单例模式是学习设计模式过程中最基本的一个设计模式,基本上一开始学习就会学到单例模式,实际上在java中实现单例模式...

  • java 单例模式

    java 单例模式

网友评论

      本文标题:Java学习笔记--单例

      本文链接:https://www.haomeiwen.com/subject/uzttnctx.html