设计模式一之单例模式

将类的构造方法设置为private,通过静态方法获取单例

/**
 * 饿汉模式:它很饿,在类的初始化时就会创建单例,类初始化创建单例时会上jvm层面的一个锁,
 * 所以不会有线程安全问题
 */
public class HungryDemo1 {

    private HungryDemo1(){
		//避免反射破坏单例
        throw new RuntimeException("无权访问该构造");
    }

    private static final HungryDemo1 hungryDemo1=new HungryDemo1();

    public static HungryDemo1 getInstance(){
        return hungryDemo1;
    }
}
/**
 * 饱汉模式:它比较饱,只有需要单例时才会创建,如果多线程同时获取单例时会出现线程安全问题可能创建出多例,
 * 可以给静态方法加synchronized关键字解决,但是这样即便单例已经创建过了,每次获取也还会上锁阻塞,
 * 所以可以改进为双重检查锁的方式,但是创建对象的过程不是一个原子操作,
 * new一个对象分为3步骤,开辟内存空间,给对象的属性赋值,将对象暴露为可用,
 * 因为jvm对代码有一个优化机制,所以可能会造成指令重排序导致第三步比第二步先执行导致对象
 * 属性未填充就提前暴露被其他线程获取这就线程不安全了,所以可以通过给单例属性加volatile关键字禁止指令重排序解决。
 */
public class LazyDemo1 {

    private LazyDemo1(){
		//避免反射破坏单例
        throw new RuntimeException("无权访问该构造");
    }

    private static volatile LazyDemo1 lazyDemo1;

    public static  LazyDemo1 getInstance(){
        if(lazyDemo1==null){
            synchronized(LazyDemo1.class){
                if(lazyDemo1==null){
                    lazyDemo1=new LazyDemo1();
                }
            }
        }
        return lazyDemo1;
    }
}

静态内部类单例
静态内部类单例也是一种懒汉模式的单例(饱汉模式)
一个类只有被获取属性或者要被使用时才会加载,而且类初始化时会有jvm层面的锁所以不会出现线程安全问题。

public class LazyDemo2 {
    
    private LazyDemo2(){
        //避免反射破坏单例
        throw new RuntimeException("无权访问该构造");
    }

    private static class Neibulei{
        static final LazyDemo2 lazyDemo2=new LazyDemo2();
    }
    
    public static LazyDemo2 getInstance(){
        return Neibulei.lazyDemo2;
    }
}

枚举单例
枚举单例是一种饿汉模式的单例,它不会被反射和序列化破坏单例,是一种很安全的单例模式

public enum HungryDemo2 {

    HUNGRY_DEMO_2;

    public static  HungryDemo2 getInstance(){
        return HungryDemo2.HUNGRY_DEMO_2;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值