单例模式详解


前言

一、单例模式的特点?

单例模式是一种常见的设计模式,它有以下特点:

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

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,总之,选择单例模式就是为了避免不一致状态

二、饿汉式单例模式

class Singleton {

    //让构造方法变为私有的,在类的外部无法创建对象
        private Singleton(){
        }
        private static Singleton singleDog=new Singleton();

        public static Singleton getSingleDog(){
            return singleDog;
        }

饿汉式在类加载的时候就创建好了一个静态的对象提供使用,以后不再改变,所以它天生就是线程安全的。

三、懒汉式单例模式

1.懒汉模式的创建

相比于饿汉模式,懒汉模式只创建我们需要的实例资源,所以他的效率更高!

class Singleton2 {
    private Singleton2(){}

    private static Singleton2 singleton=null;

    public static Singleton2 getSingleton(){
        if(singleton==null){
            Singleton2 singleton=new Singleton2();
        }
        return singleton;
    }

2.懒汉模式的线程不安全问题及解决

懒汉模式线程不安全的原因:

  • 懒汉式单例模式是线程不安全的,他有可能同时生成多个singleton对象。
  • 但是他只有在生成实例对象之前调用getSingleton方法存在线程安全问题。
  • 但是如果实例已经创建好了再去并发调用getSingleton就不会出现线程安全问题。

解决线程不安全问题的几种方法:
方式一:加对象锁

class Singleton2 {
    private Singleton2(){}

    private static Singleton2 singleton=null;

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

给getSinglenton方法加上对象锁,保证其原子性。
但是这种加锁方式再创建了实例对象之后还会每次加锁解锁操作,浪费了大量的资源!这时候我们就需要更新一下技术了!

方式二:双重检查锁定

class Singleton2 {
    private Singleton2(){}
    //加入volatile关键字避免内存可见性引来的问题
    private volatile static  Singleton2 singleton=null;


    public static Singleton2 getSingleton(){

        if (singleton==null) {  //多加了一个if判定保证效率!
            synchronized (Singleton2.class){
                if(singleton==null){
                    Singleton2 singleton=new Singleton2();
                }
            }
        }
        return singleton;
    }
 }

方式三: 静态内部类

public class Lazysingleton {
    //静态内部类
    private static class  LazyHolder{
        private  static Lazysingleton instance=new Lazysingleton();
    }

    private Lazysingleton(){}

    //在类加载的时候只创建了一个instance对象,在调用get方法的时候获得该对象。
    public static Lazysingleton getInstance(){
        return LazyHolder.instance;
    }
}

既解决了线程安全问题,又解决了浪费资源的问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

3 ERROR(s)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值