java单列模式

本文详细介绍了单例模式的五种实现方式,包括饿汉式、懒汉式、线程安全的懒汉式、双重加锁机制及静态内部类法。探讨了每种方式的特点与适用场景,帮助读者理解如何选择合适的单例模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1)饿汉式

所谓懒汉式就是在第一次加载的时候就创建对象实例,而不管实际需不需要

public Class Singleleton{
    private static Singleton singleleton= new Singleton();
    public Singleleton{};
    public Singleleton getSingleton() {
        return singleleton;
    }
}

2)懒汉式

这种方法可以实现延时加载,但是有一个致命弱点:线程不安全。如果有两条线程同时调用getSingleton()方法,就有很大可能导致重复创建对象

public Class Singleleton{
    private static Singleton singleleton= null;
    public Singleleton{};
    public Singleleton getSingleton() {
        if(singleleton==null) {
            singleleton = new Singleleton();
        }
        return singleleton;
    }
}

3)线程安全

         虽然这种写法是可以正确运行的,但是其效率低下,还是无法实际应用。因为每次调用getSingleton()方法,都必须在synchronized这里进行排队,而真正遇到需要new的情况是非常少的。

public Class Singleleton{
    private static volatile Singleton singleleton= null;
    public Singleleton{};
    public Singleleton getSingleton() {
        syschronized(Singleton.class) {
            if(singleton == null){
                singleton = new Singleton();
            }
        }
        return singleleton;
    }
}

4)双重加锁

volatile这个关键字有两层语义。第一层可见性。可见性指的是在一个线程中对该变量的修改会马上由工作内存(Work Memory)写回主内存(Main Memory),所以会马上反应在其它线程的读取操作中。工作内存是线程独享的,主存是线程共享的。v第二层语义是禁止指令重排序优化。我们写的代码(尤其是多线程代码),由于编译器优化,在实际执行的时候可能与我们编写的顺序不同。编译器只保证程序执行结果与源代码相同,却不保证实际指令的顺序与源代码相同。这在单线程看起来没什么问题,然而一旦引入多线程,这种乱序就可能导致严重问题。volatile关键字就可以从语义上解决这个问题。

volatile由于被其所修饰的变量的值不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存来实现,从而确保多个线程能正确的处理该变量。该关键字会屏蔽掉虚拟机中的一些代码优化,所以其运行效率可能不是很高,所以,一般情况下,并不建议使用双重加锁机制,酌情使用才是正理!

public class Singleton {
    private static volatile Singleton singleton = null;
    private Singleton(){}     
    public static Singleton getSingleton(){
        if(singleton == null){
            synchronized (Singleton.class){
                if(singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }    
}

5)静态内部类法

public class Singleton {
    private static class Holder {
        private static Singleton singleton = new Singleton();
    }     
    private Singleton(){}         
    public static Singleton getSingleton(){
        return Holder.singleton;
    }
}

把Singleton实例放到一个静态内部类中,这样就避免了静态实例在Singleton类加载的时候就创建对象,并且由于静态内部类只会被加载一次,所以这种写法也是线程安全的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值