Java—单例模式

什么是单例模式?

单例模式是一种软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。在单例模式中,类自身负责创建自己的唯一实例,并且保证在整个应用程序中只能访问到这个实例。

实现步骤:

  1. 私有化构造方法;
    1. 私有化构造方法,防止通过new 创建对象。
  2. 提供静态方法入口;
    1. 对外提供一个公开的静态方法,获取类的唯一实例入口。
    2. 定义成静态是为了能通过类访问,因为私有化构造方法,外界无法获取实例对象,所以不能通过实例对象访问。
  3. 定义静态变量;
    1. 定义一个私有的单例类的静态变量,在类加载的时候,初始化静态变量。
    2. 为什么是私有的:
      1. 保护单例类的安全性,禁止外界对单例类的改变。
      2. 保证单例类的唯一性,不能修改唯一实例对象。
    3. 为什么是静态的:
      1. 因为入口方法是静态的,静态方法中只能访问静态成员变量。
      2. 也符合静态的特征,在类加载时,初始化静态变量,且只执行一次。

实现(饿汉式):

        1. 提前创建好单例实例对象。

        2. 调用时,直接返回创建好的单例实例对象。

/**
*	单例模式:
* 		饿汉式
*/
public class Singleton {
	
	private String name;

	// 唯一实例对象, 静态变量
	private  static Singleton singleton = new Singleton();
		
	// 私有化构造方法; 外界就不能创建当前类对象了。
	private Singleton(){
	}

	// 提供一个外界可以获取唯一实例的入口
	public static Singleton getInstance(){
		return singleton;
	}

	public String getName(){
		return name;
	}

	public void setName(String name){
		this.name = name;
	}
}	

实现(懒汉式):

        1. 在用到时,才创建单例实例对象。

        2. 调用时,判断是否已经创建过单例实例对象,如果创建过直接返回,否则创建再返回。

/**
*     单例模式:
*          懒汉式
*/
public class Singleton {
    
    private String name;
    
    // 唯一实例对象,但是不初始化
    private static Singleton singleton;

    // 访问入口,获取单例实例对象的唯一入口。
    public static Singleton getInstance(){
        // 如果对象为空,说明时第一次访问,创建单例实例对象。
        if( singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }

    public String getName(){
        reutnr name;
    }
    
    public void setName(String name){
        this.name = name;
    }
}

多线程环境实现:

public class Singleton {
    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;
    }

    protected Object readResolve() {
        return getInstance();
    }
}

在上述代码中,通过添加volatile关键字修饰instance变量,确保多线程环境下对该变量的可见性和有序性,避免了线程安全问题。

在静态方法getInstance()中,首先检查instance是否为null,如果为null才会进入同步块。在同步块内部再次判断instance是否为null,这是为了防止多个线程同时通过第一个判断,并同时进入同步块创建实例,从而导致多个实例的产生。

此外,还需要注意到readResolve()方法的存在。当单例类被序列化后再进行反序列化时,可能会生成新的实例,为了避免这种情况,可以添加readResolve()方法,并在方法内返回单例实例。这样可以确保反序列化后获得的对象仍然是同一个实例。

这是一个完整版的单例模式示例代码,通过双重检查锁定和防止反射攻击的处理,保证了单例类的线程安全性和唯一性。

饿汉式和懒汉式的区别:

饿汉式和懒汉式是两种常见的单例模式实现方式,它们的区别主要体现在初始化时机和线程安全性上。

  1. 饿汉式:

    • 在类加载的时候就创建了对象实例,无论是否使用都会创建。
    • 在类加载过程中就完成了实例化,因此不存在多线程并发的问题。
    • 可能会浪费一些资源,因为不管有没有使用到该实例,都会提前创建。
  2. 懒汉式:

    • 延迟实例化,只有在第一次使用时才会创建对象实例。
    • 在多线程环境下,需要考虑并发访问的线程安全问题。
    • 相比饿汉式,懒汉式在不使用时不会提前创建实例,节省了一些资源。

需要注意的是,在多线程环境下使用懒汉式时,需要进行额外的处理来保证线程安全性,以避免多个线程同时创建多个实例。常见的线程安全处理方式包括使用 synchronized 关键字、双重检查锁定等。

  • 18
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值