1、final的作用:防止子类不适当的重写父类中的方法,破坏单例模式
2、私有的构造方法,只能类内第哦啊用,但是私有不能防止反射来创建新的实例
3、防止多线程并发访问问题:懒汉和饿汉有所不同
饿汉式:
静态变量的初始化,时在类加载过程(类加载只有异常)中完成,不会有多线程并发问题
package com.example.dtest.design23.singleton.hunger;
public class Mgr01 {
// 静态变量的初始化,时在类加载过程(类加载只有异常)中完成,不会有多线程并发问题
private static final Mgr01 INSTANCE = new Mgr01();
// 私有的构造方法
private Mgr01(){};
public static Mgr01 getInstance(){
return INSTANCE;
}
public void m(){
System.out.println("m");
}
}
懒汉式:双重检测
package com.example.dtest.design23.singleton.lazy;
/**
* lazy loading
* 也称懒汉式
* 虽然达到了按需初始化的目的,但却带来线程不安全的问题
* 可以通过synchronized解决,但也带来效率下降
*/
public class Mgr06 {
private static volatile Mgr06 INSTANCE;//JIT
private Mgr06(){
}
public static Mgr06 getInstance(){
// 双重检测:这里第一次判断INSTANCE是否时null
// 首次访问会同步,之后的不会再进入,但可能同时有多个已经进入第一个判断中在排队等锁
if(INSTANCE == null){
synchronized (Mgr06.class){
// 双重检测:这里第二次判断INSTANCE是否时null
if(INSTANCE == null){
INSTANCE = new Mgr06();
}
}
}
return INSTANCE;
}
public void m(){
System.out.println("m");
}
}
测试:
package com.example.dtest.design23.singleton.lazy;
public class LazyTest {
public static void main(String[] args) {
for(int i=0;i<100;i++){
new Thread(()->{
System.out.println(Mgr06.getInstance().hashCode());
}).start();
}
}
}
3、枚举类
枚举类:https://blog.csdn.net/qq_43470725/article/details/121338890
package com.example.dtest.design23.singleton.lazy.lazyEnum;
//枚举类构建的单例不能被反序列化和反射模式破坏
//INSTANCE在类加载阶段完成
//枚举类的实例只有一个INSTANCE
public enum Mgr08 {
INSTANCE;
// public void m(){
// }
public static void main(String[] args) {
for(int i=0;i<100;i++){
new Thread(()->{
System.out.println(Mgr08.INSTANCE.hashCode());
}).start();
}
}
}
测试: