单例中的懒汉与饿汉

首先对单例模式的懒汉式与饿汉式进行简单介绍:
1、饿汉式:在程序启动或单件模式类被加载的时候,单件模式实例就已经被创建。
2、懒汉式:当程序第一次访问单件模式实例时才进行创建。

如何选择:如果单件模式实例在系统中经常会被用到,饿汉式是一个不错的选择。

反之如果单件模式在系统中会很少用到或者几乎不会用到,那么懒汉式是一个不错的选择。

代码如下:

class Instance{}
//懒汉式
class LSingle{
	private static  Instance _instance = null; 
	private LSingle(){}
	
	public static Instance getInstance(){
		if(_instance==null){
			synchronized(LSingle.class){
				_instance = new Instance();
			}
		}
		return _instance;
	}
}
//饿汉式
class ESingle{
	private static Instance _instance = new Instance();
	
	private ESingle(){}
	
	public static Instance getInstance(){
		return _instance;
	}
}

单例模式用途:
单例模式属于工厂模式的特例,只是它不需要输入参数并且始终返回同一对象的引用。
单例模式能够保证某一类型对象在系统中的唯一性,即某类在系统中只有一个实例。它的用途十分广泛,打个比方,我们开发了一个简单的留言板,用户的每一次留言都要将留言信息写入到数据库中,最直观的方法是没次写入都建立一个数据库的连接。这是个简单的方法,在不考虑并发的时候这也是个不错的选择。但实际上,一个网站是并发的,并且有可能是存在大量并发操作的。如果我们对每次写入都创建一个数据库连接,那么很容易的系统会出现瓶颈,系统的精力将会很多的放在维护连接上而非直接查询操作上。这显然是不可取的。
如果我们能够保证系统中自始至终只有唯一一个数据库连接对象,显然我们会节省很多内存开销并且提高cpu利用率。这就是单例模式的用途。当然单模式不仅仅只用于这样的情况。在《设计模式:可复用面向对象软件的基础》一书中对单例模式的适用性有如下描述:
1、当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
2、当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

关于Instance类应该如何设计:
如上面叙述,我们保证单件模式类是我们取得单件实例的唯一访问点。那么我们应该保证在程序中尽量避免允许创建Instance实例。
通过将构造函数声明为private可以防止程序员通过new关键字调用构造上函数创建对象。并且在Instance类中创建getXXX()方法调用构造函数并返回具体Instance实例。具体代码如下:

class Instance{
	private Instance(){}
	
	public static Instance getSelf(){
		return new Instance();
	}
}
//懒汉式
class LSingle{
	private static  Instance _instance = null; 
	private LSingle(){}
	
	public static Instance getInstance(){
		if(_instance==null){
			synchronized(LSingle.class){
				_instance = Instance.getSelf();
			}
		}
		return _instance;
	}
}
//饿汉式
class ESingle{
	private static Instance _instance = Instance.getSelf();
	
	private ESingle(){}
	
	public static Instance getInstance(){
		return _instance;
	}
}


### 模式懒汉饿汉式的区别及实现 模式是一种常见的设计模式,确保一个类只有一个实,并提供一个全局访问点。根据实化对象的时机不同,模式可以分为懒汉式和饿汉式两种实现方式。 #### 1. 饿汉模式 饿汉模式在类加载时就完成实化,因此在使用时无需再进行判断或加锁操作。这种模式的优点是实现简、线程安全,缺点是可能会浪费内存资源,因为实在程序启动时就已经创建,即使可能永远不会被使用。 以下是饿汉模式的实现代码: ```java public class Singleton { // 在类加载时直接初始化实 private static final Singleton instance = new Singleton(); // 私有构造函数,防止外部实化 private Singleton() {} // 提供全局访问点 public static Singleton getInstance() { return instance; // 直接返回已创建的实 } } ``` 饿汉模式的特点包括: - 实在类加载时创建[^1]。 - 线程安全,无需额外的同步机制[^2]。 - 内存占用较高,因为实一旦创建就不会释放[^2]。 #### 2. 懒汉模式 懒汉模式在第一次调用 `getInstance()` 方法时才创建实,因此可以延迟实化,节省内存资源。然而,由于多线程环境下可能存在并发问题,需要通过同步机制来保证线程安全。 以下是懒汉模式的实现代码(线程不安全版本): ```java public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { // 第一次检查 instance = new Singleton(); // 可能存在线程安全问题 } return instance; } } ``` 为了解决线程安全问题,可以通过双重检查锁定(Double-Checked Locking)来优化懒汉模式: ```java 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; } } ``` 懒汉模式的特点包括: - 实在第一次调用 `getInstance()` 方法时创建[^1]。 - 内存使用效率较高,因为只有在需要时才会创建实[^2]。 - 需要额外的同步机制来保证线程安全[^4]。 #### 3. 区别总结 | 特性 | 饿汉模式 | 懒汉模式 | |------------------|-------------------------------|------------------------------------| | 实化时机 | 类加载时 | 第一次调用 `getInstance()` 时 | | 线程安全性 | 天然线程安全 | 需要额外的同步机制 | | 内存使用 | 较高,实始终占用内存 | 较低,仅在需要时创建实 | | 实现复杂度 | 简 | 较复杂,需考虑线程安全问题 | #### 4. 应用场景 模式适用于以下场景[^3]: - 系统只需要一个实对象时,如日志模块、线程池模块等。 - 资源消耗较大而只允许创建一个对象时。 - 客户端需要通过公共访问点访问同一实时。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值