首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >设计模式-单例模式

设计模式-单例模式

原创
作者头像
用户9322266
发布于 2022-10-09 10:28:12
发布于 2022-10-09 10:28:12
2290
举报
文章被收录于专栏:MYMY

概念

单例模式确保每个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

特点

  • 单例类只有一个实例
  • 单例类必须自己创建自己的一个唯一实例
  • 必须给其他对象提供这个实例好处
  • 确保全局对象的唯一性。比如系统启动读取配置文件就需要单例保证配置一致性。
  • 节省资源

线程安全问题

获取单例时,不能产生多个实例对象;

使用单例时,注意单例对象内的实例变量会被多线程共享,会有线程安全问题。

线程安全问题解决

无状态对象,阻塞式创建

实现单例模式

1. 饥汉式(静态变量)

' // 单例类

代码语言:txt
AI代码解释
复制
public class Singleton{
代码语言:txt
AI代码解释
复制
    // 类的唯一实例,静态变量, final,没有线程安全问题
代码语言:txt
AI代码解释
复制
    private final static Singleton instance = new Singleton();
代码语言:txt
AI代码解释
复制
    private Singleton(){}
代码语言:txt
AI代码解释
复制
    public static Singleton getInstance(){
代码语言:txt
AI代码解释
复制
        return instance;
代码语言:txt
AI代码解释
复制
    }
代码语言:txt
AI代码解释
复制
}

'

优点

写法简单;类装载时完成实例化;避免线程同步问题。

缺点

  • 因为类装载时实例化,没有达到懒装载(延时加载)效果;
  • 若一直不用,内存浪费。饥汉式(静态代码块)

'// 单例类

代码语言:txt
AI代码解释
复制
public class Singleton{
代码语言:txt
AI代码解释
复制
    // 类的唯一实例,静态代码块处实例化,类装载时执行静态块初始实例 
代码语言:txt
AI代码解释
复制
    final,没有线程安全问题
代码语言:txt
AI代码解释
复制
    private  static Singleton instance;
代码语言:txt
AI代码解释
复制
    static{
代码语言:txt
AI代码解释
复制
        instance = new Singleton();
代码语言:txt
AI代码解释
复制
    }
代码语言:txt
AI代码解释
复制
    private Singleton(){}
代码语言:txt
AI代码解释
复制
    public static Singleton getInstance(){
代码语言:txt
AI代码解释
复制
        return INSTANCE;
代码语言:txt
AI代码解释
复制
    }
代码语言:txt
AI代码解释
复制
}

'

优缺点同上

2. 懒汉式(线程不安全,不可用)

' // 单例类

代码语言:txt
AI代码解释
复制
public class Singleton{
代码语言:txt
AI代码解释
复制
    // 代码执行判断没有创建实例时创建唯一实例
代码语言:txt
AI代码解释
复制
    final,没有线程安全问题
代码语言:txt
AI代码解释
复制
    private  static Singleton instance;
代码语言:txt
AI代码解释
复制
    private Singleton(){}
代码语言:txt
AI代码解释
复制
    public static Singleton getInstance(){
代码语言:txt
AI代码解释
复制
        if(instance == null){
代码语言:txt
AI代码解释
复制
            instance = new Singleton();
代码语言:txt
AI代码解释
复制
        }
代码语言:txt
AI代码解释
复制
        return instance;
代码语言:txt
AI代码解释
复制
    }
代码语言:txt
AI代码解释
复制
}

'

优点

懒加载,使用时,创建;

缺点

多线程下不能使用,多线程会创建多个实例,A进入if判断,未往下执行,B也判断。产生多个实例。

3. 懒汉式(线程安全,同步方法,不推荐)

' // 单例类

代码语言:txt
AI代码解释
复制
public class Singleton{
代码语言:txt
AI代码解释
复制
    // 代码执行判断没有创建实例时创建唯一实例
代码语言:txt
AI代码解释
复制
    private  static Singleton instance;
代码语言:txt
AI代码解释
复制
    private Singleton(){}
代码语言:txt
AI代码解释
复制
    public static synchronized Singleton getInstance(){
代码语言:txt
AI代码解释
复制
        if(instance == null){
代码语言:txt
AI代码解释
复制
            instance = new Singleton();
代码语言:txt
AI代码解释
复制
        }
代码语言:txt
AI代码解释
复制
        return instance;
代码语言:txt
AI代码解释
复制
    }
代码语言:txt
AI代码解释
复制
}

'

特点

对上一种的可能引发同步问题的方法加了sychronized上锁。

阻塞式同步。

效率低,每个线程想获得实例时,执行get都要同步,实际上实例化只要一次就行,获取直接return就好。

4. 懒汉式(线程安全,同步代码块,不可用)

' // 单例类

代码语言:txt
AI代码解释
复制
public class Singleton{
代码语言:txt
AI代码解释
复制
    // 代码执行判断没有创建实例时创建唯一实例
代码语言:txt
AI代码解释
复制
    private  static Singleton instance;
代码语言:txt
AI代码解释
复制
    private Singleton(){}
代码语言:txt
AI代码解释
复制
    public static  Singleton getInstance(){
代码语言:txt
AI代码解释
复制
        if(instance == null){
代码语言:txt
AI代码解释
复制
            sychronized(Singleton.class){
代码语言:txt
AI代码解释
复制
                instance = new Singleton();
代码语言:txt
AI代码解释
复制
            }
代码语言:txt
AI代码解释
复制
        }
代码语言:txt
AI代码解释
复制
        return instance;
代码语言:txt
AI代码解释
复制
    }
代码语言:txt
AI代码解释
复制
}

'

特点

无法同步,可能产生多个实例

5. 双重检查(推荐用)

有些人认为使用 volatile 的原因是可见性,也就是可以保证线程在本地不会存有 uniqueInstance 的副本,每次都是去主内存中读取。但其实是不对的。使用 volatile 的主要原因是其另一个特性:禁止指令重排序优化。

也就是说,在 volatile 变量的赋值操作后面会有一个内存屏障(生成的汇编代码上),读操作不会被重排序到内存屏障之前。比如上面的例子,取操作必须在执行完 1-2-3 之后或者 1-3-2 之后,不存在执行到 1-3 然后取到值的情况。从「先行发生原则」的角度理解的话,就是对于一个 volatile 变量的写操作都先行发生于后面对这个变量的读操作(这里的“后面”是时间上的先后顺序)。

' // 单例类

代码语言:txt
AI代码解释
复制
public class Singleton{
代码语言:txt
AI代码解释
复制
    // 两次if,这样实例化只做一次,后面get时只return实例化对象。用volatile主要是因为new在JVM中做了3件事:1分配内存,2调用构造初始化成员变量形成实例(非null),3非将对象指向分配的内存空间(初始化完成)。JVM中有指令重排,顺序1-2-3或1-3-2.如果是后者,在3-2之间被另一线程抢占了,instance已经是非null,但是并没有初始化,另一线程会直接返回instance然后使用,这是不安全的。
代码语言:txt
AI代码解释
复制
    private  static volatile Singleton instance;
代码语言:txt
AI代码解释
复制
    private Singleton(){}
代码语言:txt
AI代码解释
复制
    public static  Singleton getInstance(){
代码语言:txt
AI代码解释
复制
        if(instance == null){
代码语言:txt
AI代码解释
复制
            sychronized(Singleton.class){
代码语言:txt
AI代码解释
复制
                if(instance == null){
代码语言:txt
AI代码解释
复制
                    instance = new Singleton();
代码语言:txt
AI代码解释
复制
                }
代码语言:txt
AI代码解释
复制
            }
代码语言:txt
AI代码解释
复制
        }
代码语言:txt
AI代码解释
复制
        return instance;
代码语言:txt
AI代码解释
复制
    }
代码语言:txt
AI代码解释
复制
}

'

优点

懒加载

线程安全

效率较高

6. 静态内部类(推荐用)

' // 单例类

代码语言:txt
AI代码解释
复制
public class Singleton{
代码语言:txt
AI代码解释
复制
    private Singleton(){} //私有,只有get方法能访问,读的时候不会同步
代码语言:txt
AI代码解释
复制
    private static  class SingletonIinstance{
代码语言:txt
AI代码解释
复制
        private static final Singleton instance = new Singleton();
代码语言:txt
AI代码解释
复制
    }
代码语言:txt
AI代码解释
复制
    public static Singleton getInstance() {
代码语言:txt
AI代码解释
复制
        return SingletonIinstance.instance;
代码语言:txt
AI代码解释
复制
    }     
代码语言:txt
AI代码解释
复制
}

'

优点

延时加载

效率高

线程安全

7. 枚举(推荐)

JDK1.5的枚举实现大力,避免同步问题,避免反序列化重现创建新的对象

' //枚举

代码语言:txt
AI代码解释
复制
public enumerate Singleton{
代码语言:txt
AI代码解释
复制
    INSTANCE;
代码语言:txt
AI代码解释
复制
}   

'

单例注意

使用相应的获取对象的方法,不要使用new

使用场景

频繁创建和销毁额对象

工具类对象

频繁访问数据库或文件的对象

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
设计模式(五):单例模式
设计模式(五):单例模式
Java架构师必看
2021/05/14
2190
设计模式二十四章经之单例设计模式
概述 单例模式是应用最广的设计模式之一。也可能是很多初级工程师唯一会使用的设计模式。从字面意思,单例模式就是单例对象的类必须保证只有一个实例的存在,而且自行实例化并向整个系统提供这个实例。例如,创建一个对象需要消耗太多的资源,如要访问IO和数据库等资源,这时需要考虑单例模式。 懒汉单例模式 线程不安全 当提到单例模式的时候,我们第一反应就是如下代码: public class Singleton { private static Singleton instance; private S
我就是马云飞
2018/06/22
4820
Java设计模式之(一)------单例模式
IT可乐
2018/01/04
9240
Java设计模式之(一)------单例模式
23设计模式之 --------- 单例模式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
默 语
2024/11/20
1150
23设计模式之 --------- 单例模式
设计模式之单例模式实践
概念 单例模式即一个JVM内存中只存在一个类的对象实例 分类 1、懒汉式 类加载的时候就创建实例 2、饿汉式 使用的时候才创建实例 当然还有其他的生成单例的方式,双重校验锁,枚举和静态内部类,文中会有
Java技术栈
2018/03/29
6720
JAVA设计模式之单例模式
public static Singleton getInstance() {
一觉睡到小时候
2019/07/04
4260
JAVA设计模式之单例模式
JAVA设计模式之单例模式
作者:炸斯特 出处:https://blog.csdn.net/jason0539 概念:   java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。 单例模式有以下特点:   1、单例类只能有一个实例。   2、单例类必须自己创建自己的唯一实例。   3、单例类必须给所有其他对象提供这一实例。   单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对
Tanyboye
2018/07/02
4070
一篇通俗易懂的文章让你彻底了解设计模式中的单例模式
之前给大家讲了关于设计模式的七大原则,这一次给大家带来了设计模式中的单例模式,以后会将23种设计模式一一为大家准备好。接下来让我们来看看单例模式吧。
@派大星
2023/06/28
2450
一篇通俗易懂的文章让你彻底了解设计模式中的单例模式
Java设计模式(一)-单例模式
单例模式(Singleton Pattern) 是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
joshua317
2021/11/24
8690
Java设计模式(一)-单例模式
一天一个设计模式:单例模式
作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化,并向整个系统提供这个实例。
用户1134788
2018/12/05
3960
单例模式
所谓饿汉式单例设计模式,就是将类的静态实例作为该类的一个成员变量,也就是说在JVM 加载它的时候就已经创建了该类的实例,因此它不会存在多线程的安全问题。
栋先生
2018/09/29
5040
单例模式
设计模式—单例模式
例如在Java开发中,我们都知道类和对象实例可以通过new来创建一个或者多个,而单例模式就是采取一定的办法保证整个系统中某一个类只能存在唯一一个对象实例,并且获取该类实例的方法只能是该类自己提供的一个获取其实例的静态方法。
炒香菇的书呆子
2022/04/18
3680
设计模式——单例模式详解
饿汉式:在类加载的时候已经创建好该单例对象。 懒汉式:在需要使用对象的时候才会去创建对象
小尘要自信
2023/10/10
1.4K0
设计模式——单例模式详解
Java设计模式——单例模式(Singleton Pattern)
从上一篇文章Java设计模式——装饰模式(Decorator Pattern)中估计大家都已经对java设计模式有了初步的理解,今天呢,阿Q就给大家讲一下另一种设计模式——单例设计模式。首先我们先来了解一下它的概念,单例模式是设计模式中最简单的形式之一,这一模式的目的是使得类的一个对象成为系统中的唯一实例,也就是保证类在内存中只有一个对象。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。它主要是为了解决全局使用的类频繁地创建与销毁浪费系统资源。
阿Q说代码
2021/05/13
9270
Java设计模式——单例模式(Singleton Pattern)
Java设计模式 | 单例模式解析与实战
确保某个类有且只有一个对象的场景, 避免产生多个对象消耗过多的资源, 或者 某种类型的对象只应该有且只有一个。 例如, 创建一个对象需要消耗的资源过多, 如要访问IO和数据库等资源,这时就要考虑使用单例模式。
凌川江雪
2020/04/14
7230
Java设计模式 | 单例模式解析与实战
设计模式【1】-- 单例模式到底几种写法?
单例模式,是一种比较简单的设计模式,也是属于创建型模式(提供一种创建对象的模式或者方式)。
秦怀杂货店
2020/12/26
4280
深入理解单例模式
Java面试通关手册(Java学习指南,欢迎Star,会一直完善下去,欢迎建议和指导):https://github.com/Snailclimb/Java_Guide
用户2164320
2018/06/14
6330
《23种设计模式(Java版)》| 单例模式(内附源码案例)。
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。
百思不得小赵
2022/12/01
3260
《23种设计模式(Java版)》| 单例模式(内附源码案例)。
Java单例模式8种方式 详解
1、单例模式(Singleton Pattern):确保某一个类最多只有一个实例,并向整个系统提供这个实例,即该类需提供一个访问唯一实例的全局方法,这个类称为单例类。单例模式的目的是使得某个类最多只有一个实例。
全栈程序员站长
2022/09/22
1.1K0
Java单例模式8种方式 详解
设计模式:单例模式 (关于饿汉式和懒汉式)
单例模式是比较常见的一种设计模式,目的是保证一个类只能有一个实例,而且自行实例化并向整个系统提供这个实例,避免频繁创建对象,节约内存。
一诺千金
2021/03/16
1.1K0
相关推荐
设计模式(五):单例模式
更多 >
LV.0
这个人很懒,什么都没有留下~
目录
  • 概念
  • 特点
  • 线程安全问题
  • 线程安全问题解决
  • 实现单例模式
    • 1. 饥汉式(静态变量)
      • 优点
      • 缺点
      • 优缺点同上
    • 2. 懒汉式(线程不安全,不可用)
      • 优点
      • 缺点
    • 3. 懒汉式(线程安全,同步方法,不推荐)
      • 特点
    • 4. 懒汉式(线程安全,同步代码块,不可用)
      • 特点
    • 5. 双重检查(推荐用)
      • 优点
    • 6. 静态内部类(推荐用)
      • 优点
    • 7. 枚举(推荐)
  • 单例注意
  • 使用场景
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档