单例模式Singleton 及其多线程

目录

 

一.单例模式的定义

单例模式的实现:

单例模式使用场景:

单例模式的优点:

单例模式的缺点:

注意事项:

单例模式类图:

单例模式Java模板:

二.单例模式与多线程

1.立即加载:“饿汉模式”

2.延迟加载:“懒汉模式”

3.静态内置类实现单例模式

4.序列化和反序列化的单例模式

5.使用static代码块实现单例模式

6.使用enum枚举数据实例实现单例模式

 


一.单例模式的定义

定义:确保其一个类只有一个实例,且自行实例化并向整个系统提供这个实例。

单例模式的实现:

通过private构造函式确保在一个应用中只产生一个实例。且自行实例化。外界通过get()函数来获取这个实例。

单例模式使用场景:

  1. 要求生成唯一序列号的环境;
  2. 整个项目中需要一个共享访问点或共享数据;
  3. 创建一个对象需要消耗的资源过多;
  4. 需要定义大量的静态常量和静态方法(如工具类)的环境;

单例模式的优点:

  1. 减少内存开销;
  2. 减少系统的性能开销(但要注意JVM的垃圾回收机制);
  3. 避免对资源的多重占用;
  4. 可以在系统中设置全局访问点。

单例模式的缺点:

  1. 单例模式一般没有接口,扩展困难;
  2. 单例模式对测试不利,如果单例模式没有完成,便不能进行测试;
  3. 单例模式与单一职责原则有所冲突。

注意事项:

克隆问题:在Java中对象默认不可复制,但是如果实现了Cloneable接口的clone()方法,则单例模式就失去了其作用。因为对象的复制不调用类的构造函数,即使构造函数私有,对象依旧可以被复制。

单例模式类图:

单例模式Java模板:

public class Singleton {
	private static final Singleton singleton = new Singleton();
	//限制产生多个对象
	private Singleton() {
		//通过该方法创造对象
	}
	public static Singleton getStingleton() {
		return singleton;
		//通过该方法获取实例对象
	}
	public static void doSomething() {
		//类中的其他方法尽量定义为static
	}
}
public class Singleton {
	private static final Singleton singleton = null;
	//限制产生多个对象
	private Singleton() {
		//通过该方法创造对象
	}
	public static Singleton getStingleton() {
		if(singleton==null) {
			singleton=new Singleton();
		}
		return singleton;
		//通过该方法获取实例对象
	}
	public static void doSomething() {
		//类中的其他方法尽量定义为static
	}
}

二.单例模式与多线程

1.立即加载:“饿汉模式”

立即加载便是实用类的时候已经将对象创建完毕,通常实现的办法为直接new实例化。

饿汉式是线程安全的,因为虚拟机保证了只会装载一次,在装载类的时候是不会发生并发的。

2.延迟加载:“懒汉模式”

延迟加载就是在调用get()方法时实例才被创建,常见的实现方法为在get()方法中进行new()实例化。

存在的问题:

在多线程环境下,延迟加载只简单这样设计就会是错误的,这样根本不能保证单例状态。会创建出多个实例。

解决办法:

  1. 声明synchronized锁即synchronized方法:给get()方法加锁。
  2. 使用同步代码块:get()方法加锁,有可能会导致运行效率低下,这时可以使用同步代码块来对判断分支语句加锁;
  3. 使用DCL双检查锁机制:同步代码块可以针对某些重要的代码进行单独的同步,而其他的代码不需要同步这样效率可以大幅提高。具体实现为,用.class锁来对new语句进行加锁。但这样仍然有可能会产生多个实例,解决的办法为在锁内再判断一次实例是否已创建。DCL是大多数多线程结合单例模式使用的解决办法。

3.静态内置类实现单例模式

使用DCL模式可以解决线程问题,也可以使用其他方法来实现多线程下的单例模式。

4.序列化和反序列化的单例模式

5.使用static代码块实现单例模式

6.使用enum枚举数据实例实现单例模式

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值