彻底玩转单例模式

彻底玩转单例模式

  • 饿汉式

    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 Hungry(){
        }
        private final static Hungry HUNGRY = new Hungry();
        public static Hungry getInstance(){
            return HUNGRY;
        }
    }
    
  • DCL 懒汉式

    //DCL 懒汉式
    public class LazyMan {
        private LazyMan() {
            System.out.println(Thread.currentThread().getName());
        }
    
        //private static LazyDemo lazyDemo;
        private volatile static LazyMan lazyMan;
    
        public static LazyMan getInstance() {
            //加锁,双重检测锁模式,DCL懒汉式
            if (lazyMan == null) {
                synchronized (LazyMan.class) {
                    if (lazyMan == null) {
                        lazyMan = new LazyMan(); //不是原子性操作,也有可能会出问题,所以需要加volatile
                    }
                }
            }
            //不加锁
    //        if(lazyMan == null){
    //            lazyMan = new LazyMan();
    //        }
            return lazyMan;
        }
    
        //单线程下单例OK,多线程并发会有问题,有可能不止一个实例,解决方法:加锁
        public static void main(String[] args) {
            for (int i = 0; i < 10; i++) {
                new Thread(() -> {
                    LazyMan.getInstance();
                }).start();
            }
        }
    }
    
     // 反射!
        public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
            //        LazyMan instance = LazyMan.getInstance();
            Field joker = LazyMan.class.getDeclaredField("joker");
            joker.setAccessible(true);
            Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
            declaredConstructor.setAccessible(true);
            LazyMan instance = declaredConstructor.newInstance();
            joker.set(instance,false);
            LazyMan instance2 = declaredConstructor.newInstance();
            System.out.println(instance);
            System.out.println(instance2);
        }
    
  • 静态内部类

    public class Holder {
        public Holder() {
        }
        public static Holder getInstace(){
            return InnerClass.HOLDER;
        }
        public static class InnerClass{
            private static final Holder HOLDER = new Holder();
        }
    }
    
  • 单例不安全,反射

  • 枚举

  • public enum EnumSingle {
        INSTANCE;
        public EnumSingle getInstance(){
            return INSTANCE;
        }
    }
    class Test {
        public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, InvocationTargetException {
            EnumSingle instance1 = EnumSingle.INSTANCE;
            Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class, int.class);
            declaredConstructor.setAccessible(true);
            EnumSingle instance2 = declaredConstructor.newInstance();
            System.out.println(instance1);
            System.out.println(instance2);
        }
    }
    
posted @ 2021-05-05 10:33  saxon宋  阅读(51)  评论(0)    收藏  举报