Java--设计模式之单例模式

java单例模式

单例模式的特点

  1. 单例类只能有一个实例;
  2. 单例类必须自己创建自己的唯一实例;
  3. 单例类必须给所有其他对象提供这一实例。

两种常用的单例类设计

懒汉式:

public class Singleton{
    private static Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance(){
        if(instance == null)
            instance = new Singleton();
        return instance;
    }
}

饿汉式:

public class Singleton{
    private static Singleton instance = new Singleton();
    private Singleton(){}
    private static Singleton getInstance(){
        return instance;    
    }
}

懒汉式顾名思义,在类加载的时候,并不对实例进行初始化,只有在用到对象的时候才初始化一个实例,这也叫做延迟加载(lazy loading)。饿汉式是在类加载的时候,就实例化,没有提供延迟加载的功能。懒汉式的延迟加载有利于节省内存,但多线程不安全;饿汉式避免了多线程的同步问题。下面看常用的三种线程安全的懒汉式单例模式

锁方法

public class Singleton{
    private static Singleton instance = null;
    private Singleton(){}
    public static synchronized Singleton getInstance(){
        if(instance == null)
            instance = new Singleton();
        return instance;
    }
}

双重锁

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

静态内部类

public class Singleton{
    private static class SingletonHolder{
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton(){}
    public static final Singleton getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

第一种锁方法的实现线程安全的方式,直接将同步关键字加在方法上,这样每次调用改方法的时候都需要进行加锁,而不管有没有实例化,而加锁的很耗时,这样效率很低。PS:99%的情况下不需要同步。

第二种双重锁的方式,只有第一次进入的方法在创建实例的时候需要加锁,以后再调用该方法都不需要加锁,提高了效率。

第三种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,它更像是一种提供了延迟加载的饿汉式方法。这种方式中Singleton类被装载,而instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。

单例模式用在哪些地方?

  1. 管理器相关的类,这种情况下管理器不能出现多个
  2. 封装配置文件的类,写成单例避免冲突
  3. 资源相关的类,如访问数据库的资源创建需要消耗较多资源
  4. 要求生成唯一序列号
  5. 需要一个共享访问点或者共享数据,比如一个计数器,可以把数值存在单例类中,而不是数据库

最佳实践

在Spring中,每个Bean默认是单例的,这样Spring容器可以管理这些Bean的生命周期。如果采用非单例模式(Prototype类型),Bean初始化后的管理交给J2EE容器,Spring容器不再跟踪管理Bean的生命周期。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值