设计模式之单例模式

单例模式

饿汉式单例模式

public class LazyMan(){
private LazyMan(){}
private final static LazyMan LAZYMAN=new LazyMan();
  public LazyMan getInstance(){
    return LAZYMAN;
  }
}

盲目的没有条件的新建对象,会造成内存的浪费

懒汉式单例模式

public class LazyMan(){
private LazyMan(){}
private final static LazyMan LAZYMAN;
  public LazyMan getInstance(){
    return new LazyMan();
  }
}

但是上面的程序在多线程情况下没有安全性可言,于是有了DSL(双锁单例模式),实际上更像是一个三🔒的模式

/**
 * DCL(Double Check Lock)单例模式,简而言之就是双锁问题,用两个锁来让对象实现原子操作。
 */
class SigleTon {
    private static boolean flag = true;

    private SigleTon () {
        synchronized (SigleTon.class) {
            if (flag ==true) {
                flag = false;
            } else {
                throw new RuntimeException ("?????");
            }
        }
        System.out.println (Thread.currentThread ().getName () + "\tOK");
    }

    private volatile static SigleTon singleton;

    /**
     * 1.分配内存空间
     * 2.执行构造方法
     * 3.将空间地址复制给变量
     * 以上3步执行完成之后,才创建完整的一个实例。
     * 因此执行顺序可能会有不同,比如123就是正常,但是由于CPU,jvm具有重排指令的功能,所以可能会导致132,一旦空间分配完成,
     * 我们就认为一个对象的实例化完成,那么另一个进程进入的时候就会以为已经完成了对韵对象的获取,那么返回的就是一个空的对象。
     * 加上volatile及时的进行可见性的使用,拒绝代码的重排
     */
    public static SigleTon getInstance () {
        if (singleton == null) {
            //只有一个类就可以使用这个代码块,:在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他的线程只能在外等着.
            //在这里,synchronized 加在这里的话,可以尽可能的减少系统开销,提高速度
            synchronized (SigleTon.class) {//第一个锁
                if (singleton == null) {//第二个锁,起到判定
                    singleton = new SigleTon ();
                }
                return singleton;
            }
        } else return singleton;
    }
}

内部类实现

class Single{
    public Single () {
    }

    public static Single getInstance(){
        return inner.SINGLE;
    }
    private static class inner{
        private  static  Single SINGLE=new Single ();
    }
}

但是这个也不是很安全,我们可以利用反射破坏结构;

所以使用枚举来实行单例模式

package JUC.Sigle;

/**
 * 枚举类实现单例模式是安全的,无法破坏原子性
 */

public enum  EnumSigle  {

    INSTANCE;

    EnumSigle () {
        System.out.println (Thread.currentThread ().getName ());
    }

    public static EnumSigle getInstance(){
        return INSTANCE;
    }
    public void fun(){
        System.out.println (this);
    }

    public static void main (String[] args) {
        for (int i = 0; i <1000 ; i++) {
            new Thread (()-> EnumSigle.getInstance ()).start ();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值