题目描述
设计一个类,我们只能生成该类的一个实例。
ref:https://blog.csdn.net/qq_38734403/article/details/106450492
饿汉模式
饿汉模式实现
/**饿汉式单例类:在类初始化时,已经自行实例化。**/
public static class SingletonHungry{
//创建对象
private static /*final*/ SingletonHungry s = new SingletonHungry();
private SingletonHungry() {}//私有化构造器
//获得唯一可用的对象
public static /*synchronized*/ SingletonHungry getInstance() {
return s;
}
}
测试
public class Client {
public static void main(String[] args) {
SingletonDemo02 s = SingletonDemo02.getInstance();
SingletonDemo02 s2 = SingletonDemo02.getInstance();
System.out.println(s==s2); //结果为true
}
}
枚举方式
public enum Singleton {
/**
* 定义一个枚举的元素,它就代表了Singleton的一个实例。
*/
INSTANCE;
/**
* 单例可以有自己的操作
*/
public void singletonOperation() {
//功能处理
}
}
懒汉模式
懒汉模式
多线程下问题:synchronized 整个代码都锁了,并发性下降, 效率不高
public class SingletonLazy {
/** 懒汉模式-多线程环境,但效率不高 */
private static SingletonLazy instance;
public static synchronized SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}
双重检测(DCL)
问题:线程不安全-指令重排
解决:private static volatile SingletonLazy instance;
public class SingletonLazy {
/**懒汉模式-双重检验锁-线程安全且并行效率高*/
private static SingletonLazy instance;
// private volatile static SingletonLazy instance; //线程安全
public static SingletonLazy getInstance() {
// 先判断实例是否存在,若不存在再对类对象进行加锁处理
if (instance == null) { //Single Checked
synchronized (SingletonLazy.class) {
if (instance == null) { //Double Checked
instance = new SingletonLazy();
}
}
}
return instance;
}
}
静态内部类
public class Singleton {
private static class SingletonClassInstance {
private static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonClassInstance.instance;
}
private Singleton() {
}
}
实现方式区别:
主要:
• 饿汉式(线程安全,调用效率高。 但是,不能延时加载。)
• 懒汉式(线程安全,调用效率不高。 但是,可以延时加载。)
其他:
• 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题。不建议使用)
• 静态内部类式(线程安全,调用效率高。 但是,可以延时加载)
• 枚举单例(线程安全,调用效率高,不能延时加载)