单例模式的几个例子

单例的作用:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。主要解决一个全局使用的类频繁地创建与销毁。
特点:
单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。
单例类必须给所有其他对象提供这一实例。
懒汉式(线程安全与非线程安全):

package com.cjs.springtest.SingletonModel;

/**
 * 懒加载模式
 * 不要求线程安全,在多线程不能正常工作
 * 这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
 * 优点:第一次调用才初始化,避免内存浪费。
 * 缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
 * getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。
 */
public class LazyModel {
    private static LazyModel lazyModel;

    private LazyModel() {
    }
/*
    //线程安全
    public static synchronized LazyModel getInstance() {
        if (null == lazyModel) {
            return new LazyModel();
        }
        return lazyModel;
    }*/

    //非线程安全 在多线程不能正常工作
    public static LazyModel getInstance() {
        if (null == lazyModel) {
            return new LazyModel();
        }
        return lazyModel;
    }
}

饿汉式:
package com.cjs.springtest.SingletonModel;

/**

  • 饿汉式
  • 这种方式比较常用,但容易产生垃圾对象。
  • 优点:没有加锁,执行效率会提高。
  • 缺点:类加载时就初始化,浪费内存。

*/
public class HungryModel {

private static HungryModel instance = new HungryModel();

private HungryModel() {
}

public static HungryModel getInstance() {
    return instance;

}

}
双重校验:

package com.cjs.springtest.SingletonModel;

/**
 * 双重校验
 * 采用双锁机制,安全且在多线程情况下能保持高性能。
 * getInstance() 的性能对应用程序很关键。
 */
public class DoubleValiteModel {

    private volatile static DoubleValiteModel singleton;

    private DoubleValiteModel() {
    }

    public static DoubleValiteModel getSingleton() {
        if (singleton == null) {
            synchronized (DoubleValiteModel.class) {
                if (singleton == null) {
                    singleton = new DoubleValiteModel();
                }
            }
        }
        return singleton;
    }
}

静态内部类:

package com.cjs.springtest.SingletonModel;

/**
 *静态内部类
 * 能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化
 * 应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
 *
 */
public class StaticInnerModel {
    private static class  SingleHolder{
        private static final StaticInnerModel INSTANCE = new StaticInnerModel();
    }
    private StaticInnerModel(){}
    public static final StaticInnerModel getInstance() {
        return SingleHolder.INSTANCE;
    }
}


枚举:

package com.cjs.springtest.SingletonModel;

/**
 * 这种实现方式还没有被广泛采用,
 * 但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
 *它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。
 *
 */
public enum EnumModel {
    INSTANCE;

    //假设此处有涉及到线程安全,需自己保证
    public void methods() {
    }
}

<think>嗯,用户让我用Java写一个单例模式例子。首先,我得回想一下单例模式的定义和用途。单例模式属于创建型设计模式,确保一个类只有一个实例,并提供全局访问点。这在需要控制资源或者共享资源时很有用,比如数据库连接池、日志对象等。 接下来,我需要考虑不同的实现方式。常见的单例实现有懒汉式、饿汉式、双重检查锁、静态内部类、枚举等。用户可能希望一个简单明了的例子,所以应该选择最典型的几种来说明。 首先是饿汉式,这个实现简单,类加载时就初始化实例,线程安全。不过可能会浪费资源,如果实例很大且不常用的话。然后是懒汉式,延迟加载,但需要考虑线程安全问题。早期的懒汉式不加同步锁的话,多线程环境下会出问题,所以需要加synchronized关键字,但这样会影响性能。 然后双重检查锁,结合了懒汉式的延迟加载和线程安全,通过两次检查实例是否存在,减少同步的开销。不过要注意volatile关键字的使用,防止指令重排序导致的问题。 静态内部类方式利用了类加载机制,静态内部类在第一次使用时才会加载,从而实现了延迟加载,并且由JVM保证线程安全。这种方式比较优雅,代码也简洁。 还有枚举方式,Effective Java推荐的方法,不仅能避免多线程问题,还能防止反序列化重新创建新对象。不过可能不太灵活,比如无法继承其他类。 用户可能需要一个具体的例子,我应该给出几种常见的实现,并说明优缺点,让用户根据场景选择。同时要提醒注意事项,比如线程安全、序列化问题、反射攻击等。 现在需要把这些整理成代码示例,用中文解释清楚每种实现的原理和适用情况。可能用户是刚开始学习设计模式,所以需要解释得详细一些,确保他们能理解不同实现方式的区别和适用场景。 还要注意代码格式,用户要求行内数学表达式用$...$,但这里主要是代码块,所以需要用正确的Java语法,可能用三个反引号包裹代码块。不过用户没有特别说明代码块的格式,但根据系统指令,可能需要使用$$...$$,但代码块通常用反引号。不过原例子里用户用了三个反引号,可能应该遵循这一点。不过原例子里用户给的是系统指令中的例子,所以可能用户希望用标准的代码块格式。 最后,要确保回答结构清晰,分点列出不同的实现方式,每种方式给出代码示例、优缺点和适用场景。这样用户能一目了然,选择适合自己需求的方式。</think>好的!单例模式是设计模式中最基础的模式之一,主要作用是保证一个类仅有一个实例,并提供全局访问点。以下是几种常见的Java实现方式及详细说明: --- ### 一、饿汉式(线程安全) ```java public class Singleton { // 类加载时直接初始化实例 private static final Singleton INSTANCE = new Singleton(); // 私有化构造方法 private Singleton() {} // 提供全局访问点 public static Singleton getInstance() { return INSTANCE; } } ``` **特点** - **线程安全**:实例在类加载时创建,由JVM保证线程安全 - **缺点**:可能浪费资源(即使未使用也会创建实例) - **适用场景**:实例较小且一定会被使用的情况 --- ### 二、懒汉式(线程不安全→改进为线程安全) ```java // 基础版(线程不安全) public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); // 多线程可能重复创建 } return instance; } } // 改进版(加锁,线程安全但性能低) public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } ``` **特点** - **延迟加载**:首次调用`getInstance()`时创建实例 - **缺点**:同步锁影响性能 - **适用场景**:单线程环境或对性能要求不高的情况 --- ### 三、双重检查锁(DCL,线程安全) ```java public class Singleton { // volatile禁止指令重排序 private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { // 第一次检查 synchronized (Singleton.class) { if (instance == null) { // 第二次检查 instance = new Singleton(); } } } return instance; } } ``` **特点** - **延迟加载 + 高效线程安全**:通过两次判空和`volatile`关键字优化性能 - **适用场景**:高并发环境 --- ### 四、静态内部类(线程安全) ```java public class Singleton { private Singleton() {} // 静态内部类在第一次使用时加载 private static class Holder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return Holder.INSTANCE; // 触发类加载并初始化实例 } } ``` **特点** - **天然线程安全**:由JVM保证类加载过程的线程安全 - **延迟加载**:内部类在调用`getInstance()`时加载 - **推荐方式**:简洁高效,无锁性能优 --- ### 五、枚举实现(最简洁的线程安全方式) ```java public enum Singleton { INSTANCE; // 枚举实例天然单例 public void doSomething() { // 功能方法 } } ``` **特点** - **绝对单例**:防止反射攻击和序列化破坏 - **代码极简**:直接通过`Singleton.INSTANCE`调用 - **推荐方式**:符合《Effective Java》建议 --- ### 关键注意事项 1. **反射攻击**:除枚举方式外,其他实现可能通过反射破坏单例(可通过构造方法中抛出异常防御) 2. **序列化安全**:若需序列化,应实现`readResolve()`方法返回已有实例 3. **多类加载器**:不同类加载器可能加载多个实例(需统一类加载器环境) 实际开发中推荐优先选择 **静态内部类** 或 **枚举** 实现方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值