美文网首页
创建型之单例模式

创建型之单例模式

作者: FisherTige_f2ef | 来源:发表于2021-01-27 18:53 被阅读0次

什么是单例模式

是指应用程序全局只能创建唯一一个实例的构造模式。一般的做法是:私有化构造方法(只能由自己创建),提供一个只能创建唯一实例的方法给别人调用

单例模式的类型

1、饿汉模式:线程严格安全,但不属于懒加载

public class Singleton {

    private static Singleton instance = new Singleton(); 

    private Singleton (){} 

    public static Singleton getInstance() { 

    return instance; 

    }  }

还有两个多此一举的,所谓的饿汉模式。其实就使用上面那种就可以了(可以忽略掉)

饿汉静态内部类模式(多此一举,不如直接使用简单饿汉模式):线程严格安全,不属于懒加载

public class Singleton {

    private static class SingletonHolder { 

    private static final Singleton INSTANCE = new Singleton(); 

    } 

    private Singleton (){} 

    public static final Singleton getInstance() { 

    return SingletonHolder.INSTANCE; 

    }  }

饿汉枚举模式(多此一举,不如直接使用简单饿汉模式):线程严格安全,但不属于懒加载

public enum Singleton {

    INSTANCE; 

    public void whateverMethod() { 

    }  }

2、懒汉线程不安全模式:线程不安全,属于懒加载

public class Singleton {

    private static Singleton instance; 

    private Singleton (){} 

    public static Singleton getInstance() { 

    if (instance == null) { 

        instance = new Singleton(); 

    } 

    return instance; 

    }  }

3、懒汉线程安全模式:线程不严格安全,属于懒加载

public class Singleton {

    private static Singleton instance; 

    private Singleton (){} 

    public static synchronized Singleton getInstance() { 

    if (instance == null) { 

        instance = new Singleton(); 

    } 

    return instance; 

    }  }

4、懒汉volatile双重检验锁模式:线程严格安全,属于懒加载

public class Singleton {

    private volatile static Singleton singleton; 

    private Singleton (){} 

    public static Singleton getSingleton() { 

    if (singleton == null) { 

        synchronized (Singleton.class) { 

        if (singleton == null) { 

            singleton = new Singleton(); 

        } 

        } 

    } 

    return singleton; 

    }  }

注意:懒加载是指,当需要调用实例时再检查是否已有实例,没有实例则创建一个实例;非懒加载就是在应用实例创建之初,就创建并加载到内存里的情况

使用建议:一般在单线程情况下使用第2种方式,如果有多线程需求,一定不允许因为线程原因导致创建两个实例,可以考虑使用第 4 种双检锁方式,或者饿汉模式。

单例模式的原理

这里重点讲懒汉volatile双重检验锁模式,其它的比较简单就不细讲了

1、双重检验锁解决了什么问题

第一次判断是否为空,是在Synchronized同步代码块外,如果已经创建了singleton对象,就不用进入同步代码块,不用竞争锁,直接返回前面创建的实例,提高效率。

第二次判断是否为空,是在Synchronized同步代码块内,假若线程A通过了第一次判断,进入了同步代码块,但是还未执行,线程B就进来了(线程B获得CPU时间片),线程B也通过了第一次判断(线程A并未创建实例,所以B通过了第一次判断),准备进入同步代码块,假若这个时候不判断,就会存在这种情况:线程B创建了实例,此时恰好A也获得执行时间片,如果不加以判断,那么线程A也会创建一个实例,就会造成多实例的情况。

2、volatile解决了什么问题

volatile的作用有两个:

一是,所有线程都能及时获得共享内存的最新状态。

即被volatile修饰的变量,每次读取前必须先从主内存刷新最新的值。每次写入后必须立即同步回主内存当中。

二是,防止指令重排

new 创建对象,并不是一个原子操作,它可以抽象为一下几条jvm指令

memory = allocate(); //1:分配对象的内存空间

initInstance(memory);//2:初始化对象

instance = memory;  //3:设置instance指向刚分配的内存地址

上面操作2依赖于操作1,但是操作3并不依赖于操作2,所以JVM可以以“优化”为目的对它们进行重排序,多线程情况下,导致可能出现误判为空的情况。

而被volatile修饰的变量,会遵循以下原子操作规则:

read、load、use动作必须连续出现

assign、store、write动作必须连续出现

因此,volatile修饰该单例能在更细的粒度保证数据在多线程的情况里的一致性,被免误判为空的情况。

ps:Java变量的读写,主要通过以下几种原子操作完成工作内存和主内存的交互

lock:作用于主内存,把变量标识为线程独占状态。

unlock:作用于主内存,解除独占状态。

read:作用主内存,把一个变量的值从主内存传输到线程的工作内存。

load:作用于工作内存,把read操作传过来的变量值放入工作内存的变量副本中。

use:作用工作内存,把工作内存当中的一个变量值传给执行引擎。

assign:作用工作内存,把一个从执行引擎接收到的值赋值给工作内存的变量。

store:作用于工作内存的变量,把工作内存的一个变量的值传送到主内存中。

write:作用于主内存的变量,把store操作传来的变量的值放入主内存的变量中

单例模式的应用场景

对于一些全局通用的实例,但是创建消耗代价很大,容易被重复创建的场景都可使用,例如:图片加载实例,语音服务实例等。

相关文章

  • 开发之设计模式-单例模式

    设计模式 设计模式分为三大类:创建型、结构型、行为型在Java中有24中设计模式 创建型:单例 1、为什么用单例模...

  • 2.架构设计(单例模式设计)

    1.设计模式分为三个类 创建型 结构型 行为型 2.创建型:单例模式 为什么用单例模式?如果你看到这个问题,你怎么...

  • 【设计模式】创建型设计模式汇总

    创建型设计模式汇总 1. 单例模式 1.1 单例模式的定义 一个类只允许创建一个对象或实例。 1.2 单例模式的作...

  • 单例模式

    单例 单例模式,是一种设计模式,属于创建型设计模式,还有一种创建型设计模式,工厂模式。设计模式总共有23种,三大类...

  • 23种设计模式学习总结

    创建型设计模式 主要解决对象的创建问题,封装复杂的创建过程,解耦对象的创建代码合使用代码。 单例模式 单例模式用来...

  • 创建型之单例模式

    什么是单例模式 是指应用程序全局只能创建唯一一个实例的构造模式。一般的做法是:私有化构造方法(只能由自己创建),提...

  • S4. 单例模式

    单例模式(Singleton) 介绍 单例模式是创建型设计模式,即用于创建对象的设计。其能够保证当前系统仅存在一个...

  • Python 之单例模式

    简介:单例模式(Singleton Pattern) 是最简单的设计模式之一,属于创建型的设计模式。单例模式涉及到...

  • iOS架构探究--单例模式

    设计模式分为三大类:创建型、结构性、行为型。单例模式就属于创建类。 1.为什么用单例模式? 由开发者的编程习惯...

  • “Python的单例模式有四种写法,你知道么?”——孔乙己

    什么是单例模式 单例模式(Singleton Pattern)是最简单的设计模式之一。这种类型的设计模式属于创建型...

网友评论

      本文标题:创建型之单例模式

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