前言
初学总结,如有问题还请大家指正
单例模式的使用场景
需要频繁的进行创建和销毁对象时,但又要经常使用到的对象、工具类对象、频繁访问数据库或文件的对象(比如 数据源、session 工厂等),
由于耗时过多或耗费资源过多从而使用单例模式.
一、单例模式创建
1.饿汉式
定义:
饿汉式构建是一种以空间换取时间的方式,
在类装载结束后,实例就会被创建出来,不管你用或者不用它就在那里,
在之后的使用中,直接进行调取即可无需判断.
优点:
线程安全,容易实现
缺点:
初始化时速度较慢
public class Singleton {
//创建 SingleObject 的一个对象
private static Singleton instance = new Singleton ();
//让构造函数为 private,这样该类就不会被实例化
private Singleton (){}
//获取唯一可用的对象
public static Singleton getInstance(){
return instance;
}
}
2.懒汉式
定义:
与饿汉式相反,懒汉式采取的是时间换空间的方式,
体现了缓存的思想,**延时加载**就是一开始不要加载资源或者数据,
一直等到马上就要使用这个资源或者数据了,在开始创建对象.
优点:
初始化速度较快
缺点:
在不加同步的时候,是线程不安全的
public class Singleton {
// 1.先创建一个null对象实例
private static Singleton instance = null;
// 2.让构造函数为 private,这样该类就不会被实例化
private Singleton() {}
// 3.提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
实现线程安全懒汉式(双重加锁校验)
public class Singleton {
private volatile static Singleton instance = null;
// 私有化构造方法
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
3.使用静态内部类
public class Singleton {
private static class SingletonHoler {
/**
* 静态初始化器,由JVM来保证线程安全
*/
private static Singleton instance = new Singleton();
}
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHoler.instance;
}
}
当getInstance方法第一次被调用的时候,它第一次读取SingletonHolder.instance,导致SingletonHolder类得到初始化;而这个类在装载并被初始化的时候,会初始化它的静态域,从而创建Singleton的实例,由于是静态的域,因此只会在虚拟机装载类的时候初始化一次,并由虚拟机来保证它的线程安全性.
4.枚举
public enum Singleton {
uniqueInstance;// 定义一个枚举的元素,它 就代表了Singleton的一个实例
public void singletonOperation() {
// 功能处理
System.err.println("功能处理");
}
}
二、防止破坏单例模式
- 反射
定义一个全局变量,当第二次创建的时候抛出异常 - 反序列化
**
* 序列化对单例的破坏,解决方案
* @author IT_LittleBaby
*
*/
public class SingletonTest10 {
public static void main(String[] args) throws Exception{
System.out.println("-----------序列化----------------------");
Singleton originSingleton = Singleton.getInstance();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(Singleton.getInstance());
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Singleton serializeSingleton = (Singleton) ois.readObject();
System.out.println(originSingleton == serializeSingleton);//false
System.out.println("-----------反射----------------------");
//通过反射获取
Constructor<Singleton> cons = Singleton.class.getDeclaredConstructor();
cons.setAccessible(true);
Singleton reflextSingleton = cons.newInstance();
System.out.println(reflextSingleton == originSingleton);//false
System.out.println("---------------------------克隆----------------------");
Singleton cloneSingleton = (Singleton) originSingleton.clone();
System.out.println(cloneSingleton == originSingleton);//false
}
}
- 克隆
添加readResolve(),返回Object对象
private static class Singleton implements Serializable,Cloneable{
private static volatile boolean isCreate = false;//默认是第一次创建
/**
* 1.构造方法私有化,外部不能new
*/
private Singleton() {
if(isCreate) {
throw new RuntimeException("已然被实例化一次,不能在实例化");
}
isCreate = true;
}
//2.本类内部创建对象实例
private static volatile Singleton instance;
//3.提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return instance;
}
/**
* 防止序列化破环
* @return
*/
private Object readResolve() {
return instance;
}
}