单例模式

单例模式是设计模式中的一种,确保类只有一个实例并提供全局访问点。其主要特点是线程安全和懒加载。本文详细介绍了单例模式的饿汉式和饱汉式的实现,包括线程不安全、线程安全以及双重检查锁(DCL)的实现方式,并分析了各种实现的优缺点。同时,提到了volatile关键字在解决DCL问题中的作用。
摘要由CSDN通过智能技术生成

什么是单例模式?

单例模式是一种常用的软件设计模式,在应用这个模式时,单例对象的类必须保证只有一个实例存在,整个系统只能使用一个对象实例。不会频繁地创建和销毁对象,浪费系统资源。使用场景:IO 、数据库连接、Redis 连接等。

单例模式有 3 个特点:

  1. 单例类只有一个实例对象;
  2. 该单例对象必须由单例类自行创建;
  3. 单例类对外提供一个访问该单例的全局访问点。

单例模式的优点:

  • 单例模式可以保证内存里只有一个实例,减少了内存的开销。
  • 可以避免对资源的多重占用。
  • 单例模式设置全局访问点,可以优化和共享资源的访问。


单例模式的缺点:

  • 单例模式一般没有接口,扩展困难。如果要扩展,则除了修改原来的代码,没有第二种途径,违背开闭原则。
  • 在并发测试中,单例模式不利于代码调试。在调试过程中,如果单例中的代码没有执行完,也不能模拟生成一个新的对象。
  • 单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。

 

单例模式代码实现饿汉式:天生线程安全

public class Singleton {

    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {

        return instance;

    }



    public static void main(String[] args) {

        Singleton singleton1 = Singleton.getInstance();

        Singleton singleton2 = Singleton.getInstance();

        System.out.println(singleton1 == singleton2);

    }

}      

饱汉式:懒加载,线程不安全

public class Singleton {

private static Singleton instance;

     public static Singleton getInstance() {

        if(instance == null)

            instance = new Singleton();

            return instance;

    }



    public static void main(String[] args) {



        Singleton singleton1 = Singleton.getInstance();

        Singleton singleton2 = Singleton.getInstance();

        System.out.println(singleton1 == singleton2);

    }

}

饱汉式变种1线程安全:加synchronized 关键字,缺点同步效率低

public class Singleton {

private static Singleton instance;

     public synchronized static Singleton getInstance() {

        if(instance == null)

            instance = new Singleton();

            return instance;

    }



    public static void main(String[] args) {



        Singleton singleton1 = Singleton.getInstance();

        Singleton singleton2 = Singleton.getInstance();

        System.out.println(singleton1 == singleton2);

    }

}

       或者

public class Singleton {

private static Singleton instance;

    public static Singleton getInstance() {

        synchronized(Singleton.class){

            if(instance == null)

                instance = new Singleton();

                return instance;

        }

    }

    public static void main(String[] args) {



        Singleton singleton1 = Singleton.getInstance();

        Singleton singleton2 = Singleton.getInstance();

        System.out.println(singleton1 == singleton2);

    }

}

饱汉式变种2:双重检查锁(Double Check Lock,简称DCL)变种2的核心是DCL,看起来变种2似乎已经达到了理想的效果:懒加载+线程安全。可惜的是,正如注释中所说,DCL仍然是线程不安全的,由于指令重排序,你可能会得到“半个对象”,即”部分初始化“问题。

public class Singleton {

    private static Singleton instance;

    public static Singleton getInstance() {

        if(instance == null){

            synchronized(Singleton.class){

                if(instance == null) {

                    instance = new Singleton();

                }



            }

        }

        return instance;

    }



    public static void main(String[] args) {



        Singleton singleton1 = Singleton.getInstance();

        Singleton singleton2 = Singleton.getInstance();

        System.out.println(singleton1 == singleton2);

    }



}

饱汉式变种3:变种3专门针对变种2,可谓DCL 2.0。针对变种3的“半个对象”问题,变种3在instance上增加了volatile关键字,可达到线程安全

public class Singleton {

    private static volatile Singleton instance;

    public static Singleton getInstance() {

        if(instance == null){

            synchronized(Singleton.class){

                if(instance == null) {

                    instance = new Singleton();

                }



            }

        }

        return instance;

    }



    public static void main(String[] args) {



        Singleton singleton1 = Singleton.getInstance();

        Singleton singleton2 = Singleton.getInstance();

        System.out.println(singleton1 == singleton2);

    }



}

文章知识点概括来自

http://c.biancheng.net/design_pattern/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值