单例模式及其多种实现

说到单例模式,大家都很熟悉,这好像是最简单的一个最简单也是容易被问的一个设计模式。以下是几种实现单例模式的方式,一个单例模式肯定有一个私有的构造方法。

(1)饿汉式

public class SingletonObject1 {
    
    private SingletonObject1(){
        
    }
    private static SingletonObject1 singletonInstance=new SingletonObject1();
    
    public static SingletonObject1 getSingletonInstance(){
        return singletonInstance;
    }
}

         饿汉式就如同它的名字,一开始就直接初始化,是线程安全的。但是如果这个实例不被使用而一开始就直接初始化,会浪费内存空间,没有懒加载。

(2)懒汉式

public class SingletonObject2 {
    private SingletonObject2(){

    }
    private static SingletonObject2 singletonInstance;
    
    public static SingletonObject2 getSingletonInstance(){
        if(singletonInstance==null){
            singletonInstance=new SingletonObject2();
        }
        return SingletonObject2.singletonInstance;
    }
}

懒汉式在需要使用他的时候才进行加载,但是在多线程的情况下,可能会new出多个实例,是线程不安全的。

(3)懒汉式同步方法

public class SingletonObject3 {
    private SingletonObject3(){

    }
    private static SingletonObject3 singletonInstance;

    public synchronized static SingletonObject3 getSingletonInstance(){
        if(singletonInstance==null){
            singletonInstance=new SingletonObject3();
        }
        return SingletonObject3.singletonInstance;
    }
}

因此,提出了在获取实例的方法加上synchronized关键字,但是同步方法是方法串行化,影响性能

(4)同步代码块双重验证

public class SingletonObject4 {
    private SingletonObject4(){

    }
    private static SingletonObject4 singletonInstance;

    public  static SingletonObject4 getSingletonInstance(){
       if(singletonInstance==null){
           synchronized (SingletonObject4.class){
               if(singletonInstance==null){
                   singletonInstance=new SingletonObject4();
               }
           }
       }
        return SingletonObject4.singletonInstance;
    }
}

    为了提高性能,采用了同步代码块加双重验证的方法,但是这种方式在多线程情况下,指令重排序可能会引起空指针异常

(5)加volatile关键字

public class SingletonObject5 {
    private SingletonObject5(){

    }
    private volatile static SingletonObject5 singletonInstance;

    public  static SingletonObject5 getSingletonInstance(){
       if(singletonInstance==null){
           synchronized (SingletonObject5.class){
               if(singletonInstance==null){
                   singletonInstance=new SingletonObject5();
               }
           }
       }
        return SingletonObject5.singletonInstance;
    }
}

volatile关键字可以禁止指令重排序。JVM对指令重排序是基于对代码运行速度进行优化的原则,禁止指令重排序会降低性能

(6)静态内部类

public class SingletonObject6 {
    private SingletonObject6(){

    }
    
    private static class single{
        private  static SingletonObject6 singletonInstance=new SingletonObject6();
    }
    
    public static SingletonObject6 getSingletonInstance(){
        return  single.singletonInstance;
    }


}

       外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化singletonInstance,故而不占内存。只有当getSingletonInstance()方法第一次被调用时,才会去初始化singletonInstance,第一次调用getSingletonInstance()方法会导致虚拟机加载single类,且仅加载这一次。这种方法不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。

(7)枚举

public enum SingletonObject7 {
    SINGLETONINSTANCE
}

枚举在java中与普通类一样,都能拥有字段与方法,而且枚举实例创建是线程安全的,在任何情况下,它都是一个单例。我们可直接以SingletonObject7 .SINGLETONINSTANCE的方式调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值