单例模式之懒汉式和饿汉式

目录

单例模式

懒汉式和饿汉式

懒汉式: 默认不会实例化,用的时候 new

饿汉式代码实现:

懒汉式和饿汉式区别: 

懒汉模式:

饿汉模式:

执行效率上:

性能上:


单例模式

特点 : 只产生一个实例

  1. 作用:一个类有且仅有一个实例,属于设计模式中的创建型模式
  2. 特点:只产生一个实例
  3. 写法:懒汉式,饿汉式

懒汉式和饿汉式

懒汉式: 默认不会实例化,用的时候 new

public class Singleton {
 //默认不会实例化,什么时候用就什么时候new
    private static Singleton instance = null;
    private Singleton(){

    }
    public static synchronized Singleton getInstance(){
        if(instance == null){
   //什么时候用就什么时候new
            instance = new Singleton();
        }
        return instance;
    }
}

饿汉式代码实现:

public class Singleton {
 //一开始类加载的时候就实例化,创建单实例对象
    private static Singleton instance = new Singleton();
    private Singleton(){

    }
    public static Singleton getInstance(){
        return instance;
    }
}

懒汉式和饿汉式区别: 

懒汉模式:

在类加载的时候不被初始化。

饿汉模式:

在类加载时就完成了初始化,但是加载比较慢,获取对象比较快。

饿汉模式是线程安全的,在类创建好一个静态对象提供给系统使用,懒汉模式在创建对象时不加上synchronized,会导致对象的访问不是线程安全的。

synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。它包括两种用法:synchronized 方法和 synchronized 块。

Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍可以访问该object中的非加锁代码块。

执行效率上:

  1. 饿汉式没有加任何的锁,因此执行效率比较高。
  2. 懒汉式一般使用都会加同步锁,效率比饿汉式差。

性能上:

  1. 饿汉式在类加载的时候就初始化,不管你是否使用,它都实例化了,所以会占据空间,浪费内存。
  2. 懒汉式什么时候需要什么时候实例化,相对来说不浪费内存。

 

 

<think>首先,用户的问题是:“我想了解单例模式懒汉饿汉式的区别以及instance关键字的使用。请问单例模式 懒汉 vs 饿汉式 区别 instance关键字用法。” 关键点: - 解释单例模式懒汉饿汉式的区别。 - 解释instance关键字的使用。 从系统指令中: - 所有行内数学表达使用$...$格。 - 独立公使用$$...$$格并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 - 回答结构清晰,帮助用户逐步解决问题。 - 参考站内引用:[^1], [^2], [^3], [^4]。 站内引用是关于Java单例模式的实现: - [^1]: 饿汉式单例模式。 - [^2]: 懒汉单例模式(普通懒汉)。 - [^3]: 懒汉单例模式(线程不安全)。 - [^4]: 饿汉式单例模式,包括代码解释。 我需要基于这些引用构建回答,但用户的问题是“instance关键字的使用”,在引用中,instance似乎是变量名或类名的一部分,不是Java关键字。在Java中,instance通常用于单例模式中表示单例实例的变量名。 在引用中: - [^1]: private static SingleTon singleTon = new SingleTon(); - [^2]: private static LazyMan lazyMan; - [^3]: private static Singleton3 instanse; // 注意拼写错误,应该是instance - [^4]: private static Singleton person = new Singleton("xx"); 所以,instance在这里是成员变量的名称,代表单例实例。Java中没有instance关键字;它只是一个变量名。 用户可能误解了,或者是在问instance在单例模式中的用法。 现在,构建回答结构: 1. 介绍单例模式。 2. 解释饿汉式懒汉。 3. 比较它们的区别。 4. 解释instance变量(不是关键字)的使用。 5. 生成相关问题。 使用中文回答。 步骤: - 清晰结构:分步骤或分节。 - 引用相关段落:自然地添加引用标识。 - 生成相关问题:在最后添加§§相关问题§§部分。 详细内容: 1. **单例模式简介**:单例模式确保一个类只有一个实例,并提供一个全局访问点。常用于资源管理、配置对象等。 2. **饿汉式**: - 在类加载时就创建实例。 - 优点:线程安全,因为实例在类初始化时创建。 - 缺点:可能造成资源浪费,如果实例未被使用。 - 代码示例:参考[^1][^4]。 - 例如:private static Singleton instance = new Singleton(); // 在类加载时初始化 3. **懒汉**: - 在第一次使用时创建实例。 - 优点:延迟加载,节省资源。 - 缺点:普通懒汉线程不安全;需要同步机制来保证线程安全。 - 代码示例:参考[^2][^3]。 - 例如:private static Singleton instance; public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } 4. **区别**: - 初始化时机:饿汉式在类加载时初始化;懒汉在第一次调用getInstance()时初始化。 - 线程安全:饿汉式天生线程安全;懒汉需要额外处理(如synchronized或双重检查锁)。 - 性能:饿汉式可能浪费资源;懒汉有性能开销在同步上。 - 资源利用:懒汉更高效,如果实例不总是需要。 5. **instance变量**: - 不是Java关键字,而是单例模式中用于存储单例实例的静态变量。 - 通常命名为instance,如private static Singleton instance; - 在getInstance()方法中访问初始化。 - 引用中使用了singleTon、lazyMan、instanse(拼写错误)、person等变量名,但概念相同。 6. **相关问题生成**: - 基于主题,如优化、线程安全、应用场景。 - 例如: 1. 如何实现线程安全的懒汉单例模式? 2. 单例模式在哪些场景下适用? 3. 饿汉式懒汉的性能比较如何? 确保LaTeX格:问题中没有数学表达,所以可能不需要,但如果有变量名,可以用$...$,如$instance$。 回答结构: - 开头:直接回答问题。 - 主体:分节解释。 - 结尾:生成相关问题。</think>### 单例模式懒汉 vs 饿汉式 区别及instance用法详解 单例模式是一种设计模,确保一个类只有一个实例,并提供全局访问点。它常用于资源管理(如数据库连接池)或配置对象。下面我将逐步解释懒汉饿汉式的区别,以及`instance`变量的用法(注意:`instance`不是Java关键字,而是单例模式中用于存储实例的静态变量名)。 #### 1. **饿汉式单例模式** 饿汉式在类加载时就创建实例,因此实例在程序启动时已存在。 **特点**: - **线程安全**:由于实例在类初始化时创建,多线程环境下无需额外同步。 - **资源消耗**:可能造成资源浪费,如果实例未被使用。 - **实现简单**:直接静态初始化变量。 代码示例(参考引用[^1][^4]): ```java public class Singleton { // 静态变量instance在类加载时初始化 private static Singleton instance = new Singleton(); // 私有构造器,防止外部创建实例 private Singleton() {} // 全局访问点,直接返回已创建的实例 public static Singleton getInstance() { return instance; } } ``` 在这个例子中,`instance`变量在类加载时被赋值为`new Singleton()`,确保任何时候调用`getInstance()`都返回同一个对象[^1][^4]。 #### 2. **懒汉单例模式** 懒汉在第一次调用`getInstance()`方法时才创建实例,实现延迟加载。 **特点**: - **延迟初始化**:节省资源,实例只在需要时创建。 - **线程不安全风险**:普通实现中,多线程环境下可能导致多个实例被创建(需额外处理,如`synchronized`)。 - **性能开销**:同步机制可能影响性能。 代码示例(参考引用[^2][^3]): ```java public class Singleton { // 静态变量instance初始为null,延迟初始化 private static Singleton instance; private Singleton() {} // 第一次调用时创建实例(线程不安全) public static Singleton getInstance() { if (instance == null) { // 判断实例是否已存在 instance = new Singleton(); // 创建新实例 } return instance; } } ``` 这里,`instance`变量初始为`null`,在`getInstance()`中检查并初始化。但多线程下,多个线程可能同时进入`if (instance == null)`块,导致创建多个实例[^2][^3]。 #### 3. **懒汉 vs 饿汉式 关键区别** | 方面 | 饿汉式 | 懒汉 | |--------------|----------------------------------|----------------------------------| | **初始化时机** | 类加载时创建实例(立即加载) | 第一次调用`getInstance()`时创建(延迟加载) | | **线程安全** | 天生线程安全(无竞争条件)[^1] | 普通实现线程不安全;需同步机制(如双重检查锁)[^3] | | **资源效率** | 可能浪费资源(实例总被创建)[^4] | 更高效(实例按需创建)[^2] | | **性能** | 访问快(无同步开销) | 同步版本有性能开销 | | **适用场景** | 实例必定被使用且资源不敏感 | 实例可能不被使用或资源敏感 | #### 4. **instance变量的用法** 在单例模式中,`instance`是一个静态变量(通常命名为`instance`或类似),用于存储类的唯一实例。它不是Java关键字,而是开发者的命名约定。 **核心用法**: - **声明**:定义为`private static`,确保全局唯一封装性(如`private static Singleton instance;`)。 - **初始化**: - 饿汉式:直接赋值(如`= new Singleton();`)。 - 懒汉:在`getInstance()`中延迟赋值。 - **访问**:通过`public static`方法(如`getInstance()`)返回`instance`,禁止外部直接访问。 在引用代码中,变量名有差异(如`singleTon`、`lazyMan`、`instanse`),但作用相同:持有单例实例[^1][^2][^3][^4]。 **注意事项**: - 变量名应清晰(如用`instance`),避免拼写错误(引用[^3]中误写为`instanse`)。 - 懒汉需处理线程安全,例如添加`synchronized`或使用双重检查锁。 #### 总结 - **选择建议**:如果资源充足且需线程安全,优先用饿汉式;如果需延迟加载,用懒汉并添加同步机制。 - **最佳实践**:在Java中,推荐使用枚举或静态内部类实现单例,以兼顾线程安全延迟加载。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

丶观海听涛丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值