单例模式是JAVA中最简单的设计模式之一,单例模式属于对象创建型模式。
作用:保证一个类只有一个实例,并提供一个访问它的全局访问点。
好处:保证对象在内存中仅有一个,减少内存开销。
常用于重量级对象,这个类创建对象是耗时,耗内存和复杂的。
饿汉式
立即创建,线程安全。在类加载时就会创建这个类的实例
1、创建唯一实列
public class SingletonClass{
private static final SingletonClass ONLY = new SingletonClass();
}
2、重写私有构造方法,屏蔽外部new的方式创建对象
public class SingletonClass{
private static final SingletonClass ONLY = new SingletonClass();
private SingletonClass(){}
}
3、提供一个全局访问点
public class SingletonClass{
private static final SingletonClass ONLY = new SingletonClass();
private SingletonClass(){}
public static SingletonClass getInstance(){
return ONLY;
}
}
双重验证式懒汉式
延迟加载、线程安全、同步情况下效率高、实现复杂
1、创建唯一实列
public class SingletonClass{
//禁止指令重排优化
private static volatile SingletonClass ONLY;
}
2、重写私有构造方法,屏蔽外部new的方式创建对象
public class SingletonClass{
//禁止指令重排优化
private static volatile SingletonClass ONLY;
private SingletonClass(){}
}
3、提供一个全局访问点
两次判断ONLY是否为空并加了同步,是为了避免在多线程环境中,对象被创建多次,而new完后后面的线程不需要同步等待,故可以加快速度
public class SingletonClass{
//禁止指令重排优化
private static volatile SingletonClass ONLY;
private SingletonClass(){}
public static SingletonClass getInstance(){
if(null == ONLY){
synchronized(SingletonClass.class){
if(null == ONLY){
ONLY = new SingletonClass();
}
}
}
return ONLY;
}
}
类加载方式
类加载特点:外部调用时是不会加载对象的内部类的代码,java虚拟机里面的类加载过程是保证线程安全的、类加载时对象就被创建好,这里我们就利用类加载的特性。
1、防止反序列化的方式
不实现Serializable或者自定义反序列化过程。
public class SingletonClass{
private SingletonClass(){}
private static class OnlyInstanceholder{
private static SingletonClass ONLY = new SingletonClass();
}
public static SingletonClass getInstance(){
return OnlyInstanceholder.ONLY;
}
private Object readResolve() throws ObjectStreamException{
return getInstance();
}
}
2、防克隆(clone)
不实现Cloneable接口或者自定义克隆过程
public class SingletonClass{
private SingletonClass(){}
private static class OnlyInstanceholder{
private static SingletonClass ONLY = new SingletonClass();
}
public static SingletonClass getInstance(){
return OnlyInstanceholder.ONLY;
}
private Object readResolve() throws ObjectStreamException{
return getInstance();
}
@Override
protected Object clone() throws CloneNotSupportedException{
return getInstance();
}
}
枚举方式
枚举是 JDK 1.5 中引入的新特性
JAVA在枚举的序列化和反序列化做了特殊规定
枚举类型极其定义的枚举变量在JVM中都是唯一的
枚举的构造器只在构造枚举值的时候被调用,构造器私有private,不允许有public构造器
枚举元素INSTANCE表示SingletonClass的一个实例
public enum SingletonClass {
INSTANCE;
}