1.单例模式

本文深入解析单例模式的定义、特点及其六种实现方式:懒汉模式、饿汉模式、双检锁模式、内部类模式、枚举实现。对比各模式的优缺点,如线程安全性、资源消耗等,推荐使用内部类模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例模式

1.定义

  • 所谓单例,就是整个程序有且仅有一个实例。该类负责创建自己的对象,同时要确保只有一个对象被创建。

  • 好处:就是一个类你只能创建一个实例对象可以节约内存开销,一般常用于在工具类的实现(之前的静态方法也可以用于工具类的实现)。

2.特点

  1. 构造器私有
  2. 持有自己类的属性
  3. 对外提供获取实例的静态方法

一般单例模式分为两大类:懒汉模式,饿汉模式.详细分其实有懒汉,饿汉,双检锁,内部类,枚举。

3.懒汉模式

/**
 * 	懒汉模式,延迟初始化,在调用方法获取的时候才会实例对象
 * 	线程不安全的,严格意义上不是单例模式
 * @author Administrator
 *
 */
public class Singleton {
	//持有自己类型的属性
	private static Singleton instance;
	
	//构造方法私有化
	private Singleton() {}
    
	//对外提供获取实例的静态方法
	public static Singleton getInstance() {
		if(instance==null) {
			instance=new Singleton();
		}
		return instance;
	}	
}

测试

public class Test {
	public static void main(String[] args) {
		Singleton instance1 = Singleton.getInstance();
		Singleton instance2 = Singleton.getInstance();
		System.out.println(instance1==instance2);
	}
}

结果

true

4.饿汉模式

线程安全,比较常用,但是容易产生垃圾,因为饿汉模式一开始加载类的时候就初始化了实例。

/**
 * 	饿汉模式
 * @author Administrator
 *
 */
public class Singleton {
	//持有自己类型的属性
	//由于static修饰,只在加载类的时候执行一次
	private static Singleton instance = new Singleton();
	
	//构造方法私有化
	private Singleton() {}

	//对外提供获取实例的静态方法
	public static Singleton getInstance() {
		return instance;
	}
}

测试

public class Test {
	public static void main(String[] args) {
		Singleton instance1 = Singleton.getInstance();
		Singleton instance2 = Singleton.getInstance();
		System.out.println(instance1==instance2);
	}
}

结果

true

懒汉模式和饿汉模式的区别

  1. 懒汉是非线程安全,饿汉是线程安全
  2. 懒汉模式是一开始不实例化对象,调用方法时才实例化对象,饿汉模式一开始实例化对象,容易造成资源浪费.

综合两者的优缺点,可以使用双检锁模式。

5.双检锁模式

双检锁也称双重校验锁,综合了懒汉模式和饿汉模式的优缺点

/**
 * 	双检锁模式结合懒汉模式和饿汉模式的优点:延迟加载并且线程安全
 * @author Administrator
 *
 */
public class Singleton {
	
	//持有自己类型的属性
	private volatile static Singleton instance;
	
	//构造方法私有化
	private Singleton() {}
	
	//对外提供获取实例的静态方法
	public static Singleton getInstance() {
		if(instance==null) {
			synchronized(Singleton.class) {
				if(instance==null) {
					instance=new Singleton();
				}
			}	
		}
		return instance;
	}
}

小结:

  • 双检锁模式,进行两次判断,第一次判断是为了避免不要的实例,第二次是为了进行线程同步,避免多线程问题,由于newsingleton()创建instance对象的时候jvm中可能会重新排序,在多线程存在风险,使用volatile关键字可以当线程改变其值后通知其他线程已改变并且不会被java重新排序,解决该问题

6.内部类模式

/**
 * 	内部类模式实现单例模式
 * @author Administrator
 *
 */
public class Singleton {
	private Singleton() {}
	
	public static Singleton gatInstance() {
		return Inner.instance;
	}
	
	public static class Inner{
		//final修饰的常量,不能再被改变
		private static final Singleton instance= new Singleton();
	}
}

小结

  • 只有第一次调用gatInstance()方法时,虚拟机才加载Inner内部类并初始化instance,只有一个线程可以获取instance对象的初始化,其他线程无法再进行初始化,线程安全的,保证对象的唯一性。【推荐使用此方式实现单例模式】

7.枚举实现

/**
 * 	默认枚举的实例是线程安全的,并且在任何情下都是单例
 * 	枚举类默认隐藏了所有的构造方法
 * 
 * @author Administrator
 *
 */
public enum Singleton {
	INSTANCE;
	
	public static Singleton getInstance() {
		return Singleton.INSTANCE;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值