单列模式

单列模式


前言

参考文献:单列模式

**单例模式的含义**
通过单例模式可以保证系统中, 应用该模式的这个类永远只有一个实例。即一个类永远只有一个对象实例。 单例是为了节约内存,也可以适用于一些需要保证在程序运行期间,对象不被改变的场景。

单例的应用场景:

    在实际开发中,有很多业务对象永远只需要一个,无论启动多少次
    我们只需要一个对象,例如任务管理对象,只需要一个对象。节约内存和性能。
     因为对象越多内存占用越大,极有可能出现内存溢出!

单例模式的两种方式

饿汉单例设计模式
在用类获取对象的时候,对象已经提前创建好了。
设计步骤:
a.定义一个类,把构造器私有。
b.定义一个静态变量存储一个对象。

懒汉单例设计模式
在真正需要该对象的时候,才去创建一个对象(延迟加载对象)。
设计步骤:
a.定义一个类,把构造器私有。
b.定义一个静态变量存储一个对象。
c.提供一个返回单例对象的静态方法。

一、饿汉创建

public class SingletonDemo1 {
    //在 类加载的时候,有且会唯一创建一次对象
    public static SingletonDemo1 singletonDemo1=new SingletonDemo1();

    private SingletonDemo1(){//将构造器私有,确保无法在外部创建该类的对象
    System.out.println("单列对象被创建");

    }
}

二、懒汉创建

懒加载的原则,在需要的时候才会创建单列对象。

1.直接创建 (线程不安全)

public class SingletonDemo2 {
    private static SingletonDemo2 singletonDemo2;
    private SingletonDemo2(){
        System.out.println("单列对象被创建");
    }
    //线程不安全
    public static SingletonDemo2 getSingletonDemo2(){
        if(singletonDemo2==null){//如果为空则创建
            singletonDemo2=new SingletonDemo2();
        }
       return singletonDemo2; //对象不为空直接返回,时候唯一创建一次对象
    }
}

2.静态同步方法

保证了线程的安全,但是锁粒度大,一次只能有一个线程访问,执行的效率太低。

public class SingletonDemo3 {
    private static SingletonDemo3 singletonDemo3;
    private SingletonDemo3(){
        System.out.println("创建单列对象");
    }
    //提供一个线程安全的静态方法,获取单列对象,该锁是当前类
    public static synchronized SingletonDemo3 getSingletonInstance(){
        if(singletonDemo3==null){//为空则创建
            singletonDemo3=new SingletonDemo3();
        }
        //不为空则直接返回
        return singletonDemo3;
    }

}

3、同步代码块实现(双重检查)

这里适用同步代码块,锁住的是不为空时创建对象的代码,并且增加了一次实列对象是否存在检查,有效避免了线程安全问题,又可以减少锁的使用,有效提高了效率。

public class SingletonDemo4 {
    private static SingletonDemo4 singletonDemo4;
    private SingletonDemo4(){
        System.out.println("创建单列对象");
    }
    //提供一个线程安全的静态方法,获取单列对象,该锁锁住的是当前类
    public static  SingletonDemo4 getSingletonInstance(){
        if(singletonDemo4==null){//这次检查是为了减少 synchronized 锁被开启的次数
            synchronized(SingletonDemo4.class){
                if(singletonDemo4==null){ //保证了只创建一次 实列对象
                    singletonDemo4=new SingletonDemo4();
                }
            }
        }
        return singletonDemo4;
    }
}

4、静态内部类

在这里插入图片描述
静态内部类的方式效果类似双检锁,但实现更简单。但这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。

5、枚举(完美方式)

枚举的方式是比较少见的一种实现方式,但是看上面的代码实现,却更简洁清晰。并且她还自动支持序列化机制,绝对防止多次实例化。

public enum SingletonDemo5 {
    INSTANCE;//SingletonDemo5.INSTANCE就可获取单列对象


    //类当中的方法
    public void print(){
        System.out.println("我是单列对象的方法");
    }
}

总结

原文链接:https://blog.csdn.net/absolute_chen/article/details/93380566

好了,上面就是单例模式的五种主要写法。我们来总结下,一般情况下,懒汉式(包含线程安全和线程不安全梁总方式)都比较少用;饿汉式和双检锁都可以使用,可根据具体情况自主选择;在要明确实现 lazy loading 效果时,可以考虑静态内部类的实现方式;若涉及到反序列化创建对象时,大家也可以尝试使用枚举方式。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值