java设计模式——单例模式



一、什么情况下考虑使用“单例模式”?
          
        单例模式使得一个类在任何情况下只有一个对象,通常当需要一个类来管理共享的资源(例如:线程池、注册表,缓存等)可以使用单例模式,因为我们需要保证这些全局资源只有一份。

        单例模式的概念:

        单例模式确保一个类只能有一个实例,而且为这个实例提供了一个全局访问点。

二、如何实现单例模式?

        ①将构造方法私有化

        ②通过一个private静态变量记录单例类的唯一实例。

        ③定义一个获取该实例静态方法。        实现如下:

public class Singleton {
    private static Singleton singleton;

    private Singleton(){} //构造方法私有化

    public static Singleton getInstance(){
        if(singleton == null)
            singleton = new Singleton();
        return singleton;
    }

 以上便实现了简单的单例模式,但是在多线程时可能会出现错误,所以需要对程序进行简单的修改如下:

 

对getInstance()方法添加同步锁:

 

public static synchronized Singleton getInstance() {
        if (singleton == null)
            singleton = new Singleton();
        return singleton;
    }

 这样可以保证在其他线程进入getInstance()方法时需等待其他方法执行完getInstance()方法。

 

 

然而如果程序访问getInstance()方法的频率很高,这就会产生效率问题,我们可以采用单例中的饿汉模式,代码如下:

 

public class Singleton {
    private static Singleton singleton = new Singleton();

    private Singleton() {
    } //构造方法私有化

    public static  Singleton getInstance() {
        return singleton;
    }
}

 这样就可以使得JVM在加载这个类时就创建这个类的唯一实例,那么即使在多线程中也不会出现问题。

 

 

        然而如果程序中我们可能很多情况下不要调用这个类的话,加载马上就创建实例,又会造成很大的浪费,我们该怎么办呢?

       可以使用“双重检查加锁”,在getInstance()中减少使用同步,只有在创建实例时添加同步锁,代码如下:

 

public class Singleton {
    private volatile static Singleton uniqueInstance;

    private Singleton() {
    } //构造方法私有化

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

 注意:uniqueInstance使用了volatile关键词修饰,volatile使得线程对缓存中数据的修改强制的写入主存,同时使得cpu中其他的线程缓存无效,需要从主存中重新读取(对多线程我也不太了解,以后慢慢学习吧)。

需要注意的是“双重检查加锁”不适用java 1.4及其以前版本。

 

在维基百科中也找到了关于延迟加载同时又避免加锁的另一个版本

     In software engineering, the Initialization on Demand Holder (design pattern) idiom is a lazy-loaded singleton. In all versions of Java, the idiom enables a safe, highly concurrent lazy initialization with good performance.

 

public class Singleton {
    private static class LazyHolder{
       private static final Singleton uniqueInstance = new Singleton();
    }

    private Singleton() {
    } //构造方法私有化

    public static  Singleton getInstance() {
        return LazyHolder.uniqueInstance;
    }
}

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值