定义:确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。
条件:隐藏所有构造方法、提供一个全局访问点。
例如:ServletContext、ServletConfig、ApplicationContext
一、饿汉式单例
/**
* 优点:执行效率高,性能高,没有任何的锁
* 缺点:某些情况下,可能会造成内存浪费
*/
public class HungrySingleton {
//final关键词 防止对象变值
private static final HungrySingleton hungrySingleton = new HungrySingleton();
private HungrySingleton(){}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
}
二、饿汉式静态单例
public class HungryStaticSingleton {
//先静态后动态
//先上,后下
//先属性后方法
private static final HungryStaticSingleton hungrySingleton;
//更加的灵活,加入逻辑控制语句
static {
hungrySingleton = new HungryStaticSingleton();
}
private HungryStaticSingleton(){}
public static HungryStaticSingleton getInstance(){
return hungrySingleton;
}
}
三、懒汉式简单式单例
/**
* 优点:节省了内存
* 缺点:线程不安全
*/
public class LazySimpleSingletion {
//不需要final,延迟加载的时候赋值
private static LazySimpleSingletion instance;
private LazySimpleSingletion(){}
//加锁,防止冲突,线程不安全,不是单例
public final static LazySimpleSingletion getInstance(){
if(instance == null){
instance = new LazySimpleSingletion();
}
return instance;
}
}
四、懒汉式线程安全单例
/**
* 优点:节省了内存,线程安全
* 缺点:效率低,性能低
*/
public class LazySimpleSingletion {
//不需要final,延迟加载的时候赋值
private static LazySimpleSingletion instance;
private LazySimpleSingletion(){}
//加锁,防止冲突,防止线程不安全,不是单例
public synchronized final static LazySimpleSingletion getInstance(){
if(instance == null){
instance = new LazySimpleSingletion();
}
return instance;
}
}
五、懒汉式双重检查锁单例
/**
* 优点:性能高了,线程安全了
* 缺点:可读性难度加大
*/
public class LazyDoubleCheckSingleton {
//加入volatile关键词可解决指令重排问题
private static LazyDoubleCheckSingleton instance;
private LazyDoubleCheckSingleton(){}
public static LazyDoubleCheckSingleton getInstance(){
//检查是否要排队
if (instance == null) {
synchronized (LazyDoubleCheckSingleton.class) {
//检查是否要重新创建实例
if (instance == null) {
instance = new LazyDoubleCheckSingleton();
}
}
}
return instance;
}
}
六、懒汉式静态内部类单例
/*
ClassPath : LazyStaticInnerClassSingleton.class 加载时只扫描主类
LazyStaticInnerClassSingleton$LazyHolder.class 内部类
优点:写法优雅,利用了Java本身语法特点,性能高,避免了内存浪费,不能被反射破坏
线程安全:访问之前就加载好了
缺点:可读性难度加大
*/
public class LazyStaticInnerClassSingleton {
private LazyStaticInnerClassSingleton(){
//防止反射强行破坏 c.setAccessible(true)反射后强行访问私有构造方法
//枚举类不可以强行破坏
if(LazyHolder.INSTANCE != null){
throw new RuntimeException("不允许非法访问");
}
}
private final static LazyStaticInnerClassSingleton getInstance(){
//访问时不加载
return LazyHolder.INSTANCE;
}
private static class LazyHolder{
//访问之前就加载好了
private static final LazyStaticInnerClassSingleton INSTANCE = new LazyStaticInnerClassSingleton();
}
}
七、枚举单例
public enum EnumSingleton {
INSTANCE;
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static EnumSingleton getInstance(){return INSTANCE;}
}
破坏单例:序列化:需调整readResolve()方法
克隆破坏:重写clone()方法