4、单例模式

2019-12-16  本文已影响0人  lois想当大佬

一、单例模式-饿汉模式
1、定义一个不可变的静态变量并直接实例化
2、构造函数私有化
3、定义一个静态函数总是返回实例

package com.hello.single;

/**
 * 单例模式-饿汉模式
 * 1、定义一个不可变的静态变量并直接实例化
 * 2、构造函数私有化
 * 3、定义一个静态函数总是返回实例
 *
 * 问题:
 * 1、EhanSingle类在加载字节码到虚拟机的时候就会实例化这个实例,
 * 在你没有使用该单例的时候,该单例却被加载了,如果该单例很大的话,将会浪费很多的内存
 */
public class EhanSingle {

    private static final EhanSingle single = new EhanSingle();

    private EhanSingle(){}

    public static EhanSingle getInstance() {
        return single;
    }
}

存在问题:
1、EhanSingle类在加载字节码到虚拟机的时候就会实例化这个实例,在你没有使用该单例的时候,该单例却被加载了,如果该单例很大的话,将会浪费很多的内存。

二、单例模式-懒汉模式
1、定义一个静态变量实例
2、定义一个静态函数创建并返回实例
3、私有化构造函数

package com.hello.single;

/**
 * 单例模式-懒汉模式
 * 1、定义一个静态变量实例
 * 2、定义一个静态函数创建并返回实例
 * 3、私有化构造函数
 * 问题
 * 1、多线程环境下不能保证单例
 */
public class LanhanSingle1 {


    private static LanhanSingle1 single;

    private LanhanSingle1(){};

    public static LanhanSingle1 getInstance() {
        // 如果对象不是null,就直接返回实例,从而保证单例。也可以保证不浪费内存(不调用则不产生对象)
        if (single == null) {
            single = new LanhanSingle1();
        }
        return single;
    }
}

存在问题:
1、多线程环境下不能保证单例

三、单例模式-懒汉模式-加锁
1、定义一个静态变量实例
2、定义一个静态函数创建并返回实例
3、私有化构造函数
4、同步锁确保在多线程环境下保证单例

package com.hello.single;

/**
 * 单例模式-懒汉模式
 * 1、定义一个静态变量实例
 * 2、定义一个静态函数创建并返回实例
 * 3、私有化构造函数
 * 4、同步锁确保在多线程环境下保证单例
 * 问题
 * 1、正确的对象实例化流程:
 * a、在堆空间分配内存
 * b、执行构造方法进行初始化
 * c、将对象指向内存中分配的内存空间,也就是地址
 * 2、但是,由于编译器会对代码进行重排序优化,如果执行的顺序是acb,则也会产生错误对象。
 */
public class SynLanhanSingle2 {


    private static SynLanhanSingle2 single;

    private SynLanhanSingle2(){};

    public static SynLanhanSingle2 getInstance() {
        // 多线程访问,不做控制、不影响性能
        if (single == null) {
            // 此时,如果多个线程进入,则进入同步块
            synchronized (SynLanhanSingle2.class) {
                // 此时,第一个进入的线程判断为null,但是第二个线程进来时已经不是null了
                if (single == null) {
                    single = new SynLanhanSingle2();
                }
            }
        }
        // 如果不为null,不会影响性能,只有第一次才会影响性能
        return single;
    }
}

四、 单例模式-懒汉模式-静态内部类
1、静态内部类实例化对象
2、定义一个静态函数返回实例
3、私有化构造函数

package com.hello.single;

/**
 * 单例模式-懒汉模式
 * 1、静态内部类实例化对象
 * 2、定义一个静态函数返回实例
 * 3、私有化构造函数
 * 问题:
 * 1、反射破坏
 * 2、反序列化破坏
 */
public class InnerLanhanSingle3 {

    private InnerLanhanSingle3(){};

    public static InnerLanhanSingle3 getInstance() {
        return InnerClass.single;
    }

    /**
     * 静态内部类的虚拟机机制,只有当访问类的时候,才会加载,
     * 因此, 既保证了懒加载(节省内存),又保证了单例与线程安全。
     */
    private static class InnerClass{
        private static final InnerLanhanSingle3 single = new InnerLanhanSingle3();
    }
}

上一篇:模板方法模式

上一篇下一篇

猜你喜欢

热点阅读