java设计模式之单例模式5种方法及优缺点小结

单例设计模式的用处。

单例设计模式是指,某个类只有一个实例。在计算机系统中类似于打印机和最常见的就是任务管理器的对话框,不管几个用户同时登录windows 打开的任务对话框只有一个。

常见的几种实现方式:

1.lazy-load
/* 适合单线程模式 延迟加载 lazy-load*/
public class Singleton {

    /* 私有的静态对象变量,来标记是否初始化过 也用来把实例化进行缓存*/
    private static Singleton instance = null;
    /* 私有的构造函数防止外部调用 */
    private Singleton (){}
    /* 供外部调用的接口是public的其余均为private */
    public static Singleton getInstance(){
        /* 单线程模式先如果对象变量为空,那么需要创建 */
        /* 但是多线程下这个地方需要同步,否则会出现两个线程都创建了一个实例的情况 */
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }

}
2.lazy-load的变种1线程安全了但是效率很差
/* 多线程下可以使用但是如果两个线程同时想创建实例的化,加锁和等待锁是很耗时的
如果不想创建实例了但是还要获取锁,这样很不好。 lazy-load */
public class Singleton{
    private static Singleton instance = null;
    private Singleton(){

    }
    public static synchronized Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}
3,lazy-load的变种2线程安全了,效率有提高
/* 对上一种方式进行了优化,提前判断一下变量是否为空,前后两次判断是否存在 lazy-load */
/* 但是这种两次if判断的存在出错的情况 */
/*  */
public class Singleton{
    /* 此处使用volatile关键字 */
    private volatile static Singleton instance = null;
    private Singleton(){}
    public static  Singleton getInstance(){
        /* 第一次判断 隔绝在已经实例之后调用get接口获取实例对象的情况,放置这些情况仍然调用锁 */
        if(instance == null){
        /* 防止两个线程同时进行创建实例 */
            synchronized(Singleton.class){
            /* 这个if判断也是必须的,如果出现了两个线程同时等待锁,但是第一个线程释放之后,第二个线程进入但是却没有判断锁是否释放的化,那么仍然是创建了两次,同时这个instance也一定是volatile 的保证可见性 */
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

但是这样的doubleif仍然有问题。虽然使用了volatile 虽然两次if判断。
因为无序写入:

这个double if 判断的参考了这个写的特别好,值得学习
引申:

4.饿汉式
/* 饿汉式,类加载就会创建实例而不去管你用不用, 但是内存使用率低 线程安全。因为虚拟机保证了类只会加载一次,在装载类的时候是不会并发的 */
public class Singleton{
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return instance;
    }
}
5.静态内部类
/* 静态内部类 */
/* 由于内部类不会在加载外部类的时候进行加载,那么这个也属于lazy-load。但是这种延迟加载的加载也是class的加载jvm保证只有一次所以同样线程安全 */
public class Singleton{
    private Singleton(){}
    private static class SingletonIneerClass{
        private final static Singleton instance = new Singleton();
    }
    public static Singleton getInstance(){
        return SingletonIneerClass.instance();
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值