JUC编程学习(三)

本文深入探讨Java中的单例模式实现,包括饿汉式、懒汉式(DCL)以及静态内部类方式,并讲解了volatile关键字如何防止指令重排。同时,通过实例展示了如何利用反射破坏单例,以及枚举单例的不可破坏性。
摘要由CSDN通过智能技术生成

3、指令重排(你写的程序,计算机并不会按照你写的去执行

源代码–>编译器优化重排–>指令并行也可能会重排–>内存系统也会重排–>执行

请添加图片描述

内存屏障、cpu指令。作用:

1、保证特定的操作的执行顺序!

2、可以保证某些变量内存的可见性(利用这些特性,就可以保持)

加了volatile是可以保持可见性,不能保证原子性,由于内存屏障,可以保证避免指令 重排

18、彻底玩转单例模式

饿汉式单例模式:

package com.huang.single;

//饿汉式单例模式
public class hungry {
    //浪费资源
    private byte[]  data1=new byte[1024*1024];
    private byte[]  data2=new byte[1024*1024];
    private byte[]  data3=new byte[1024*1024];
    private byte[]  data4=new byte[1024*1024];
    private byte[]  data5=new byte[1024*1024];
    private hungry(){
        System.out.println("i am  hungry");
    }
    private  final static hungry hungry =new hungry();
    public static hungry getInstance(){
        return  hungry;
    }
}
class test{
    public static void main(String[] args) {
       hungry.getInstance();
    }
}

懒汉式单例(双重检测锁 排除构造对象是存在的指令重排问题!):

package com.huang.single;
//Dcl懒汉式单例模式
public class LazyMan {
    private LazyMan(){
        System.out.println(Thread.currentThread().getName()+"=>ok");
    }
    private  volatile static LazyMan lazyMan;//加上volatile关键字避免出现指令重排现象
    public static LazyMan getInstance(){
        if (lazyMan==null){//双层检测加锁模式  DCL懒汉式
            synchronized (LazyMan.class){
                if (lazyMan==null){
                     lazyMan = new LazyMan();//不是一个原子性操作
                    /**
                     * 1、分配内存
                     * 2、执行构造方法,初始化对象
                     * 3、把这个对象指向这个空间
                     *存在指令重排问题!!!!!
                     * */
                }
            }
        }
        return lazyMan; //可能导致lazyman还没有构造
    }
    //多线程并发(存在问题--->加锁)
    public static void main(String[] args) {
        for (int i = 0; i <10 ; i++) {
            new Thread(()->{
                LazyMan.getInstance();
            }).start();
        }
    }
}

静态内部类:

package com.huang.single;
//静态内部类
public class Hold {
    private Hold(){
        System.out.println("hahah");
    }
    public static Hold getInstance(){
        return innerClass.hold;
    }
    public static class  innerClass{
        private static  final Hold hold= new Hold();
    }
}
class  Test{
    public static void main(String[] args) {
        Hold.getInstance();
    }
}

利用反射破坏单例模式!!!:

package com.huang.single;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
//Dcl懒汉式单例模式
public class LazyMan {
    private  static boolean huang = false;
    private LazyMan(){
        synchronized (LazyMan.class){
            if (huang==false){
                huang=true;
            }else {
                    throw  new RuntimeException("不要视图使用反射破坏异常!");
            }
        }
    }
    private  volatile static LazyMan lazyMan;
    public static LazyMan getInstance(){
        if (lazyMan==null){//双层检测加锁模式  DCL懒汉式
            synchronized (LazyMan.class){
                if (lazyMan==null){
                     lazyMan = new LazyMan();//不是一个原子性操作
                    /**
                     * 1、分配内存
                     * 2、执行构造方法,初始化对象
                     * 3、把这个对象指向这个空间
                     *存在指令重排问题!!!!!
                     * */
                }
            }
        }
        return lazyMan;
    }
    public static void main(String[] args) throws Exception {
        //反射可以破坏这种单例
//        LazyMan instance = LazyMan.getInstance();
        Field huang = LazyMan.class.getDeclaredField("huang");
        huang.setAccessible(true);
        Constructor<LazyMan> constructor = LazyMan.class.getDeclaredConstructor(null);//获取空参构造器
        constructor.setAccessible(true);
        LazyMan instance1 = constructor.newInstance();
        huang.set(instance1,false);
        LazyMan instance2 = constructor.newInstance();
        System.out.println(instance2);
        System.out.println(instance1);
    }

}

反射无法破坏枚举(枚举构造方法中存在参数(String,int)):

package com.huang.single;

import java.lang.reflect.Constructor;

//enum 1.5jdk  本身也是一个类
public enum  EnumSingle {
    INSTANCE;
    public EnumSingle getInstance(){
        return INSTANCE;
    }
}
//反射不能破坏枚举
class  Test02 {
    public static void main(String[] args) throws Exception {
        EnumSingle instance1=EnumSingle.INSTANCE;
//        Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(null);
        Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
        declaredConstructor.setAccessible(true);
        System.out.println(instance1);
        EnumSingle instance2 = declaredConstructor.newInstance();
        //运行结果 java.lang.NoSuchMethodException: com.huang.single.EnumSingle.<init>()
        System.out.println(instance2);
    }
}

nce2 = declaredConstructor.newInstance();
//运行结果 java.lang.NoSuchMethodException: com.huang.single.EnumSingle.()
System.out.println(instance2);
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值