单例模式
饿汉式
// 单例模式-饿汉式
// 缺点:在类加载时就new出了对象,可能造成浪费空间
public class Hungry {
private final static Hungry eHanDemo = new Hungry();
private Hungry(){
}
public static Hungry getInstance(){
return eHanDemo;
}
}
懒汉式
// 懒汉式:当需要用这个对象时,再进行创建
// 这样创建懒汉式存在问题:由于新建对象时不是原子操作,当多个线程同时需要创建对象,可能出现创建出多个对象。
public class LazyManDemo01 {
private static LazyManDemo01 lazyManDemo01;
private LazyManDemo01() {
}
public static LazyManDemo01 getInstance() {
if (lazyManDemo01 == null) {
lazyManDemo01 = new LazyManDemo01();
}
return lazyManDemo01;
}
}
DCL懒汉式,防止多线程情况下创建出多个对象问题
// DCL懒汉式,可防止多线程情况下创建多个对象
// 问题,当通过反射方式镜像创建对象时,还是可以创建多个对象。
public class LazyManDemo02 {
private volatile static LazyManDemo02 lazyManDemo02;
private LazyManDemo02() {
}
// 双重检测锁模式的 懒汉式单例 DCL懒汉式
public static LazyManDemo02 getInstance() {
if (lazyManDemo02 == null) {
synchronized (LazyManDemo02.class) {
if (lazyManDemo02 == null) {
lazyManDemo02 = new LazyManDemo02(); // 不是原子操作
/**
* 1. 分配内存空间
* 2. 执行构造方法,初始化对象
* 3. 把这个对象指向这个空间
* 防止指令重排,用 volatile 修饰 lazyManDemo02
*/
}
}
}
return lazyManDemo02;
}
// 反射!
public static void main(String[] args) throws Exception {
// LazyManDemo02 instance = LazyManDemo02.getInstance();
Constructor<LazyManDemo02> declaredConstructor = LazyManDemo02.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
LazyManDemo02 lazyManDemo02 = declaredConstructor.newInstance();
LazyManDemo02 lazyManDemo022 = declaredConstructor.newInstance();
System.out.println(lazyManDemo02);
System.out.println(lazyManDemo022);
}
}
设置一个flag变量,判断是否创建过对象,防止反射操作获取多个对象
但通过反射改变 flag 变量值,同样无法避免创建多个对象
// 设置一个flag变量,判断是否创建过对象,防止反射操作获取
// 问题,但通过反射也能改变 flag 的值,从而达到创建多个对象
public class LazyManDemo03 {
private volatile static LazyManDemo03 lazyManDemo03;
private static boolean flag = false;
private LazyManDemo03() {
synchronized (LazyManDemo03.class){
if (flag == false){
flag = true;
}else {
throw new RuntimeException("不要试图使用反射破坏");
}
}
}
// 双重检测锁模式的 懒汉式单例 DCL懒汉式
public static LazyManDemo03 getInstance() {
if (lazyManDemo03 == null) {
synchronized (LazyManDemo03.class) {
if (lazyManDemo03 == null) {
lazyManDemo03 = new LazyManDemo03(); // 不是原子操作
}
}
}
return lazyManDemo03;
}
}
通过查看反射源码发现,枚举类不能通过反射获取
枚举类单例
// enum 是一个什么? 本身也是一个Class类
public enum EnumSingle {
INSTANCE;
public EnumSingle getInstance(){
return INSTANCE;
}
}
枚举类介绍:https://blog.youkuaiyun.com/hellojoy/article/details/79883671