设计模式

单例模式

概念:一个类只能有一个实例对象

使用场景:计数器,不用每次刷新都在数据库里加一次,可以用单例先缓存起来

思路:

  1. 首先创建一个常量
  2. 构造方法改为私有,类外部不能创建对象
  3. 通过一个公开的方法,返回这个对象,供外部使用

饿汉式单例

特点:线程安全,但类在装载时就实例化,浪费空间

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

懒汉式单例

特点:使用时创建,线程不安全,加同步后线程安全

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

静态内部类的单例(兼具上述两种方式的优点)

class Singleton{
    private Singleton(){}
    private static class Holder{
        static Singleton _instance = new Singleton();
    }
    public static Singleton getInstance(){
        return Holder._instance;
    }
}

双检锁/双重校验锁(DCL,即 double-checked locking)

class Singleton {
    private volatile static Singleton _instance;
    private Singleton() {}
    public static Singleton getInstance(){
        if(_instance == null){   //提高效率,避免每次都要判断是否获得锁
            synchronized(Singleton.class){
                if(_instance == null){
                    _instance = new Singleton();
                }
            }
       } 
        return _instance;
    }
}

使用volatile的原因:

在new Singleton()过程有三个步骤:

  1. 在堆中开辟空间,分配地址
  2. 根据类加载的初始化顺序进行初始化
  3. 将内存地址返回给栈中的引用变量

但是Java内存模型允许无需写入,有些编译器因为性能原因可能会把2和3步进行重排序

当线程A进入并在堆中开辟空间,分配地址后,先将内存地址返回给栈中变量时,线程B此时恰好进入判断实例已经存在后便拿去使用,而此时的实例还没有完成第2步初始化动作,所以线程B拿到的实例是不可使用的。

因此在_instance前加入关键字volatile。使用了volatile关键字后,重排序被禁止,所有的写(write)操作都将发生在读(read)操作之前。 但是只在 JDK5 及之后有效。

枚举

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值