关于几种单例模式的介绍

    关于单例模式,需要解决三个方面的问题

(1)线程安全问题。

(2)性能问题。

(3)懒加载(资源占有问题)。

关于下面几种方式的缺点,除了DCL,HOLDER和枚举单例模式其他只做简单描述,具体可自行了解。

懒汉式:锁粒度过大,影响性能,串行执行影响效率,会引起阻塞。

public class Lazy {
    
    private static Lazy lazy = null;
    
    private Lazy(){}

    public synchronized static Lazy getInstance(){
        if(null == lazy){
            lazy = new Lazy();
        }
        return lazy;
    }
}

 

饿汉式:无懒加载

public class Hungry {
    private static Hungry hungry = new Hungry();

    private Hungry(){}

    public static Hungry getInstance(){
        return hungry;
    }
}

 

DCL(double-check-locking)

public class DCL {
    private static volatile DCL dcl = null;
    private DCL(){}

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

}


由于懒汉式锁粒度太大,考虑把锁加在代码块上,但是如果同时两个线程访问getInstance(),线程1获取锁,线程2做了1的判断在等待,此时如果线程1创建了dcl对象,那么如果不加3的话会重复创建,所以3必须要加,这种方式的单例模式被称为双重加锁模式。

步骤3,非原子性 分三步:1、为对象分配内存空间。2、创建对象。3、对象指向内存空间,2,3有可能重排序,但是不影响结果,第三步进行之后对象将不为null,所以如果2,3重排序,先执行3,第一个判断不为空,会返回一个对象,但实际对象还未创建,会返回NULLPOINTEXCEPTION,这就是指令重排给我们带来的影响,所以加volatail,防止指令重排。

 

Holder模式

public class Holder {

    private static class Hold{
        private static Holder holder = new Holder();
    }

    public static Holder getInstance(){
        return Hold.holder;
    }
}


创建一个获取对象的静态内部类,它里面的holder实例对象不会在类加载的时候被创建,只在被调用时被创建一次,满足所有要求。

 

枚举类模式(枚举+Holder模式)

public class EnumSingleton {

   private EnumSingleton(){}

   private enum EnumSlt{
       INSTANCE;

       private EnumSingleton enumSingleton = null;
       EnumSlt(){
           enumSingleton = new EnumSingleton();
       }
   }

   public static EnumSingleton getInstance(){
       return EnumSlt.INSTANCE.enumSingleton;
   }

}


类似Holder模式的静态内部类,首先枚举类的构造方法是私有的,这就保证不会被其他方法通过构造器new出对象,再来INSTANCE就是这个枚举类的对象,会在调用的时候被实例化,这样保证了懒加载,在实例化的时候会调用构造器,创建instance对象,因为枚举类中的对象都是static final 修饰的,所以instance对象也只会被实例化一次,这样就保证了线程安全性,因为没加锁,所以性能也相对较高。

基于ThreadLocal实现的单例模式

public class ThreadLocalSingleton {
    private static final ThreadLocal<ThreadLocalSingleton> th = new ThreadLocal() {
        @Override
        protected ThreadLocalSingleton initialValue() {
            return new ThreadLocalSingleton();
        }
    };
    private ThreadLocalSingleton() {}
    public static ThreadLocalSingleton getInstance() {
        return th.get();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值