主题:最常见的设计模式之一:单例模式
简单say一下概念:
![在这里插入图片描述](https://img-blog.csdnimg.cn/de75b5a3ed1e46828fea40dfe0904997.jpg?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA56eD5aS05bCP6YOR77yM,size_20,color_FFFFFF,t_70,g_se,x_16)
声明一点:为了节约时间,做到简洁干练,本文章参考了b站的尚硅谷所分享的教学资源
废话不多说直接撸码开干:
(一)饿汉模式:静态常量
/*
饿汉式(静态常量)
*/
public class SingleOne {
private final static SingleOne instance = new SingleOne();
private SingleOne(){}
public static SingleOne getInstance(){
return instance;
}
}
测试用例:
SingleOne singleOne1 = SingleOne.getInstance();
SingleOne singleOne2 = SingleOne.getInstance();
System.out.println(singleOne1 == singleOne2);
System.out.println("SingleOne1的hashcode== "+singleOne1.hashCode());
System.out.println("SingleOne2的hashcode== "+singleOne2.hashCode());
运行结果:说明只获得到一个实例,后面的测试用例都以此形式
优缺点分析:
(二)饿汉式:静态代码块
public class SingleTwo {
private final static SingleTwo instance;
private SingleTwo(){}
static {
instance = new SingleTwo();
}
public static SingleTwo getInstance(){
return instance;
}
}
优缺点与(一)一样,俩段代码十分相似
(三)懒汉式(线程不安全)
/*
懒汉式--线程不安全
*/
public class SingleThree {
private static SingleThree instance;
private SingleThree(){}
public static SingleThree getInstance(){
if(instance == null){
instance = new SingleThree();
}
return instance;
}
}
优缺点分析:
(四)懒汉式(线程安全)
public class SingleFour {
private static SingleFour instance;
private SingleFour(){}
public static synchronized SingleFour getInstance(){
if(instance == null){
instance = new SingleFour();
}
return instance;
}
}
优缺点分析:
(五)懒汉式–错误玩法例子
分析:
(六)双重检查:
public class SingleFive {
private static volatile SingleFive instance;
private SingleFive(){}
public static SingleFive getInstance() {
if(instance == null){
synchronized (SingleFive.class){
if(instance == null){
instance = new SingleFive();
}
}
}
return instance;
}
}
变量的关键字volatile非常重要
volatile作用:以下会涉及到Java内存模型的知识
禁止指令重排序。我们知道new Singleton()是一个非原子操作,编译器可能会重排序【构造函数可能在整个对象初始化完成前执行完毕,即赋值操作(只是在内存中开辟一片存储区域后直接返回内存的引用)在初始化对象前完成】。而线程B在线程A赋值完时判断instance就不为null了,此时B拿到的将是一个没有初始化完成的半成品。
保证可见性。线程A在自己的工作线程内创建了实例,但此时还未同步到主存中;此时线程B在主存中判断instance还是null,那么线程B又将在自己的工作线程中创建一个实例,这样就创建了多个实例。
声明:volatile参考了
https://blog.csdn.net/zcl_love_wx/article/details/80758162
(七)枚举实现单例类:(有大佬非常推荐)
public enum SingleSeven {
Instance;
public void method(){
System.out.println("hello world");
}
}
(八)静态内部类实现单例类:
public class SingleEight {
private SingleEight(){}
private static class Single{
private final static SingleEight INSTANCE = new SingleEight();
}
private static SingleEight getInstance(){
return Single.INSTANCE;
}
}
优缺点分析:
总结:红色的推荐在开发中推荐使用