09_单例模式

说明

定义:
保证一个类仅有一个实例,并提供一个全局访问点

类型:创建型

适用场景:
想确保任何情况下都绝对只有一个实例

优点:
在内存里只有一个实例,减少了内存开销
可以避免对资源的多重占用
设置全局访问点,严格控制访问

缺点:
没有接口,扩展困难

重点:
私有构造器
线程安全
延迟加载
序列化和反序列化安全
反射

一、懒汉式

1.1 双重检查机制
package com.study.single_instance.java.lazy;

public class DoubleCheckSingleInstance {
    /**
     * 禁止重排序:volatile关键字保证所有线程都能看到共享内存的状态,保证了内存的可见性。
     * 用volatile修饰的共享变量在进行写操作的时候,当前处理器缓存行的数据写回到系统内存,
     * 同时使得其它CPU缓存了该内存地址的数据无效。
     * 当处理器发现缓存无效之后,就会在去系统内存中获取数据。(缓存一致性协议)
     */
    private volatile static DoubleCheckSingleInstance doubleCheckSingleInstance=null;
    private DoubleCheckSingleInstance(){}
    public static DoubleCheckSingleInstance getInstance(){
        if(doubleCheckSingleInstance==null){
            synchronized (DoubleCheckSingleInstance.class) {
                if(doubleCheckSingleInstance==null) {
                    /**
                     * doubleCheckSingleInstance = new DoubleCheckSingleInstance();分为三步
                     * 1.分配对象的内存空间
                     * 2.初始化对象
                     * 3.设置instance指向内存空间
                     * 2或3步可以重排序
                     */
                    doubleCheckSingleInstance = new DoubleCheckSingleInstance();
                }
            }
        }
        return doubleCheckSingleInstance;
    }
}

1.2 静态内部类的方式
package com.study.single_instance.java.lazy;

public class StaticClassSingleInstance {
    private static StaticClassSingleInstance staticClassSingleInstance=null;
    private StaticClassSingleInstance(){ }

    private static class InnerInstanceHolder{
        /**
         * 只有当有线程调用getInstance方法时,staticClassSingleInstance才会被初始化。
         * Class被加载之后以及被线程使用之前都是类的初始化阶段,在这个阶段
         * JVM会执行初始化,JVM会去获取一个锁。这个锁可以同步多个线程对一个
         * 类的初始化,这时候只有持有这个锁的线程才能看到类的初始化过程中的
         * 重排序。
         *
         */
        private  static StaticClassSingleInstance staticClassSingleInstance=new StaticClassSingleInstance();
    }


    public static StaticClassSingleInstance getInstance(){
        return InnerInstanceHolder.staticClassSingleInstance;
    }
}

二、饿汉式

2.1 成员变量初始化
package com.study.single_instance.java.hungry;

import java.io.Serializable;

public class LazySingleInstance implements Serializable,Cloneable {
    private final static LazySingleInstance lazySingleInstance=new LazySingleInstance();
    private LazySingleInstance(){}
    public static LazySingleInstance getInstance(){
        return lazySingleInstance;
    }

    //用于反序列化调用,方法签名要与下列方法签名一致才可以,因为在反序列化的
    //过程中虚拟机会去检测当前内中是否存在该方法。
    public Object readResolve(){
        return lazySingleInstance;
    }
}

2.2 成员变量静态代码块初始化
package com.study.single_instance.java.hungry;

public class LazyStaticInitSingleInstance {
    private final static LazyStaticInitSingleInstance lazyStaticSingleInstance;
    static {
        lazyStaticSingleInstance = new LazyStaticInitSingleInstance();
    }
    private LazyStaticInitSingleInstance(){}
    public static LazyStaticInitSingleInstance getInstance(){
        return lazyStaticSingleInstance;
    }

}

三、多线程调试方法

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值