单例模式

单例模式

简介

保证在内存中只有一个实例

饿汉式

public class Single01 {
    //类加载初始话
    private static final Single01 INSTANCE = new Single01();
    //私有构造器
    private Single01(){

    }
    //公开方法
    public static Single01 getInstance(){
        return INSTANCE;
    }

    public static void main(String[] args) {
        Single01 instance01 = Single01.getInstance();
        Single01 instance02 = Single01.getInstance();

        System.out.println(instance01 == instance02);
    }
}

反射破解

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Single01 {
    //类加载初始话
    private static final Single01 INSTANCE = new Single01();
    //私有构造器
    private Single01(){

    }
    //公开方法
    public static Single01 getInstance(){
        return INSTANCE;
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Single01 instance01 = Single01.getInstance();
        //获得class文件
        Class<Single01> single01Class = Single01.class;
        //获取无参构造器
        Constructor<Single01> constructor = single01Class.getDeclaredConstructor();
        //暴力反射
        constructor.setAccessible(true);
        //反射实例
        Single01 single01 = constructor.newInstance();

        System.out.println(single01 == instance01);

    }
}

懒汉式

线程安全问题

/**
 * lazy load
 * 虽然按需求初始话,但是有线程安全的问题
 * 这里要加上volatile  防止指令重排
 */
public class Single02 {

    private static Single02 INSTANCE;

    private Single02(){

    }

    public static Single02 getINSTANCE(){
        if (INSTANCE == null){
            try {
                //测试
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Single02();
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(Single02.getINSTANCE());
            }).start();
        }
    }
}

解决 synchronized

/**
 * lazy load
 * 虽然按需求初始话,但是有线程安全的问题
 *  加上 synchronized 效率会下降
 */
public class Single02 {

    private static Single02 INSTANCE;

    private Single02(){

    }

    public synchronized static Single02 getINSTANCE(){
        if (INSTANCE == null){
            try {
                //测试
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Single02();
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(Single02.getINSTANCE());
            }).start();
        }
    }
}

双重检测锁

/**
 * 双重检测锁
 */
public class Single03 {

    private static Single03 INSTANCE;

    private Single03(){

    }

    public static Single03 getINSTANCE(){
        if (INSTANCE == null){
          synchronized (Single03.class){
              if (INSTANCE == null){
                  try {
                      //测试
                      Thread.sleep(1);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  INSTANCE = new Single03();
              }
          }
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(Single03.getINSTANCE());
            }).start();
        }
    }
}

反射破解

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Single04 {
    private static Single04 INSTANCE;

    private Single04(){

    }

    public static Single04 getINSTANCE(){
        if (INSTANCE == null){
            synchronized (Single04.class){
                if (INSTANCE == null){
                    try {
                        //测试
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new Single04();
                }
            }
        }
        return INSTANCE;
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Single04 instance01 = Single04.getINSTANCE();
        
        Class<Single04> single04Class = Single04.class;
        Constructor<Single04> constructor = single04Class.getDeclaredConstructor();

        constructor.setAccessible(true);

        Single04 single04 = constructor.newInstance();

        System.out.println(single04 == instance01);
    }
}

静态内部类

//开始实现懒加载
public class Single05 {
    private Single05(){

    }

    private static class HolderSingle05{
        private static final Single05 INSTANCE = new Single05();
    }
    //公开方法
    public static Single05 getInstance(){
        return HolderSingle05.INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                System.out.println(Single05.getInstance());
            }).start();
        }
    }
}

反射破解

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Single05 {
    private Single05(){

    }
	//匿名内部类
    private static class HolderSingle05{
        private static final Single05 INSTANCE = new Single05();
    }
    //公开方法
    public static Single05 getInstance(){
        return HolderSingle05.INSTANCE;
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Single05 instance = Single05.getInstance();

        Class<Single05> single05Class = Single05.class;

        Constructor<Single05> declaredConstructor = single05Class.getDeclaredConstructor();

        declaredConstructor.setAccessible(true);

        Single05 single05 = declaredConstructor.newInstance();

        System.out.println(single05 == instance);
    }
}

枚举 enum

//枚举类
public enum Single06 {
    INSTANCE;

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println(Single06.INSTANCE.hashCode());
        }
    }
}

反射破解

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

//枚举类
public enum Single06 {
    INSTANCE;

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        System.out.println(Single06.INSTANCE.hashCode());


        Class<Single06> single06Class = Single06.class;;
        Constructor<Single06> declaredConstructor = single06Class.getDeclaredConstructor();

        declaredConstructor.setAccessible(true);

        Single06 single06 = declaredConstructor.newInstance();
        System.out.println(single06.hashCode());
    }
}

抛出异常 没有空参构造

这里可以看到如果是枚举的话会报Cannot reflectively create enum objects

通过反编译可以看到构造器其实是有参数的

重新运行一下

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

//枚举类
public enum Single06 {
    INSTANCE;

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        System.out.println(Single06.INSTANCE.hashCode());


        Class<Single06> single06Class = Single06.class;;
        //在构造器传入指定参数
        Constructor<Single06> declaredConstructor = single06Class.getDeclaredConstructor(String.class,int.class);

        declaredConstructor.setAccessible(true);

        Single06 single06 = declaredConstructor.newInstance();
        System.out.println(single06.hashCode());
    }
}

抛出指定异常 It's ok

posted @ 2021-01-19 18:20  immortal_mode  阅读(83)  评论(0)    收藏  举报