Skip to content

Latest commit

 

History

History
247 lines (188 loc) · 6.1 KB

File metadata and controls

247 lines (188 loc) · 6.1 KB

设计模式

单例模式

饿汉式单例

在单利类首次加载时就创建实例

缺点:浪费内存空间

public class HungrySingleton {

    private static final HungrySingleton hungrySingleton = new HungrySingleton();
    public HungrySingleton() {
    }

    public static  HungrySingleton getInstance() {
        return hungrySingleton;
    }
}
public class HungryStaticSingleton {

    private static final HungryStaticSingleton hungrySingleton;
    static {
        hungrySingleton = new HungryStaticSingleton();
    }

    public HungryStaticSingleton() {
    }

    public static HungryStaticSingleton getInstance() {
        return hungrySingleton;
    }
}

懒汉模式

不加synchronized会出现线程不安全的问题,以下方法还是可能会出现问题。

1.普通

public class LazySimpleSingleton {
    private static LazySimpleSingleton lazySimpleSingleton = null;

    // 虽然内部类私有,但是反射可以拿到
    private LazySimpleSingleton() {
    }

    // JDK1.6 之后对synchronize性能优化不少
    // 不可避免的存在一定的性能问题
    public synchronized static LazySimpleSingleton getInstance() {
        if (lazySimpleSingleton == null) {
            lazySimpleSingleton = new LazySimpleSingleton();
        }

        return lazySimpleSingleton;
    }
}

2.改进-双重检测锁

需要牺牲一定的性能

public class LazyDoubleCheckSingleton {
    private volatile static LazyDoubleCheckSingleton lazySimpleSingleton = null;

    private LazyDoubleCheckSingleton() {
    }

    // 双重检查锁
    public static LazyDoubleCheckSingleton getInstance() {
        if (lazySimpleSingleton == null) {
            synchronized (LazyDoubleCheckSingleton.class) {
                if (lazySimpleSingleton == null) {
                    lazySimpleSingleton = new LazyDoubleCheckSingleton();
                    // CPU执行时会转换成JVM指令行
                    // 指令重排序问题
                    // 1.分配内存给这个对象
                    // 2.初始化对象
                    // 3.讲初始化好的对象和内存地址建立关联,赋值
                    // 4.用户初次访问
                }
            }
        }
        return lazySimpleSingleton;
    }
}

3.内部类模式

以下方法性能很高,但是会被反射破坏单例

// 全程没有用synchronized关键字
public class LazyInnerClassSingleton {

    // 虽然内部类私有,但是反射可以拿到
    private LazyInnerClassSingleton() {}

    // 懒汉式单例
    // LazyHolder 里面的逻辑需要等到外部方法调用时才执行
    // 巧妙的利用了内部类的特性
    // JVM 底层执行逻辑,完美避免了线程安全问题
    public static final LazyInnerClassSingleton getInstance() {
        return LazyHolder.LAZY;
    }

    private static class LazyHolder {
        private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();
    }
}

使用反射破坏单例模式

try {
            Class<?> clazz = LazyInnerClassSingleton.class;
            Constructor c = clazz.getDeclaredConstructor(null);
            c.setAccessible(true);

            Object o1 = c.newInstance();

            Object o2 = LazyInnerClassSingleton.getInstance();

            System.out.println(o1);

            System.out.println(o2);

            System.out.println(o1 == o2);

            c.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

3.改进内部类单例

// 全程没有用synchronized关键字
public class LazyInnerClassSingleton {

    // 虽然内部类私有,但是反射可以拿到
    private LazyInnerClassSingleton() {
        if (LazyHolder.LAZY != null) {
            throw new RuntimeException("不允许构建多个示例");
        }
    }

    // 懒汉式单例
    // LazyHolder 里面的逻辑需要等到外部方法调用时才执行
    // 巧妙的利用了内部类的特性
    // JVM 底层执行逻辑,完美避免了线程安全问题
    public static final LazyInnerClassSingleton getInstance() {
        return LazyHolder.LAZY;
    }

    private static class LazyHolder {
        private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();
    }
}

序列化实现单例

//反序列化时导致单例破坏
public class SeriableSingleton implements Serializable {

    //序列化就是说把内存中的状态通过转换成字节码的形式
    //从而转换一个IO流,写入到其他地方(可以是磁盘、网络IO)
    //内存中状态给永久保存下来了

    //反序列化
    //讲已经持久化的字节码内容,转换为IO流
    //通过IO流的读取,进而将读取的内容转换为Java对象
    //在转换过程中会重新创建对象new

    public  final static SeriableSingleton INSTANCE = new SeriableSingleton();
    private static final long serialVersionUID = 1463169805620377688L;

    private SeriableSingleton(){}

    public static SeriableSingleton getInstance(){
        return INSTANCE;
    }

    private  Object readResolve(){
        return  INSTANCE;
    }

}

注册式-枚举模式实现单例

public enum EnumSingleton {
    INSTANCE;

    private Object data;

    public static EnumSingleton getInstance() {
        return INSTANCE;
    }

    public Object getData() {
        return data;
    }
}

注册式-容器注册单例模式

public class ContainerSingleton {
    private ContainerSingleton() {
    }

    private static Map<String, Object> ioc = new ConcurrentHashMap<>();

    public static Object getBean(String className) {
        synchronized (ioc) {
            if (!ioc.containsKey(className)) {
                Object obj = null;
                try {
                    obj = Class.forName(className).newInstance();
                    ioc.put(className, obj);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return obj;
            }
            return ioc.get(className);
        }
    }
}