单例模式

标签:java设计模式—–实验楼


Java设计模式—-单例模式

什么是单例模式(Singleton Pattern):

就是被单例的对象只能有一个实例存在。单例模式的事项方式是:一个类只能返回对象的一个引用(永远是同一个)和一个获得该唯一实例的方法(必须是静态方法)通过单例模式,我们可以保证系统中只有一个实例,从而在某些特定的场合下达到节约或者控制系统资源的目的

单例模式类图

此处输入图片的描述

单例模式实例

单例模式有很多种的实现

  • 饿汉模式
  • 懒汉模式
  • 线程安全的懒汉模式
  • 双重检验锁
  • 静态内部类
  • 枚举
饿汉模式

最常见的就是饿汉模式,最简单。一上来就是新建一个实例。但是这种方法有一个明显的缺点就是不管有没有获得过实例的方法,每次都会新建一个实例

public class Wife {
    // 一开始就新建一个实例,这是自引用?
    private static final Wife wife = new Wife();

    // 默认的构造方法
    public Wife() {
        // TODO Auto-generated constructor stub
    }

    // 获得实例的方法
    public static Wife getWife() {
        return wife;
    }
}
懒汉模式

最常见,最简单之二。就是开始的时候不创建实例,只有在需要使用的时候才创建实例,会先判断实例是否为空,如果为空才会新建一个实例来使用

public class Wife {
    // 一开始没有新建一个实例
    private static  Wife wife;

    // 默认的构造方法
    public Wife() {
        // TODO Auto-generated constructor stub
    }

    // 需要时才创建
    public static Wife getWife() {
        if (wife == null) {
            wife = new Wife();
        }
        return wife;
    }
}
线程安全的懒汉模式

懒汉模式确实很简单,但是要注意的是上面的懒汉模式存在一个严重的问题。就是如果有多个线程并行使用getWife()方法的时候,还是会创建多个实例,单例模式就失效了。
于是我们在懒汉模式的基础上,把它设为线程同步。synchronized的作用就是保证在同一时刻最多只有一个线程运行,这样就避免了多线程带来的麻烦

public class Wife {
    // 一开始没有新建一个实例
    private static Wife wife;

    // 默认的构造方法
    public Wife() {
        // TODO Auto-generated constructor stub
    }

    // 添加了关键字
    public static synchronized Wife getWife() {
        if (wife == null) {
            wife = new Wife();
        }
        return wife;
    }
}
双重检验锁

线程安全的懒汉模式解决了多线程的问题,但那时效率并不高,每次调用获取实例的getWife()方法时都要进行同步,但是多数情况下是不需要进行同步操作的(比如在wife实例并不为空可以直接使用的时候,就不需要加同步方法,直接返回实例),所以只需要在第一次新建实例对象的时候使用同步方法

getWife()方法的双重检验锁
public static Wife getWife() {
        if (wife == null) {//第一次为空的时候
            synchronized (Wife.class){//同步创建
                if (wife==null) {
                    wife=new Wife();
                }
            }
        }
        return wife;
    }

注意这里并没有结束,主要问题在于wife=new Wife()因为在JVM执行这句代码的时候,要做好几件事情,而JVM为了优化代码,有可能造成做这几件事情的执行顺序是不固定的,从而造成错误。因此我们要阻止代码自行进行优,于是加上一个volatile关键字
“`java
//双重检验锁的最终式
public class Wife {
// 一开始没有新建一个实例
private volatile static Wife wife;

// 默认的构造方法
public Wife() {
    // TODO Auto-generated constructor stub
}

// 需要时才创建
public static Wife getWife() {//第一次为空的时候
    if (wife == null) {
        synchronized (Wife.class){//同步创建
            if (wife==null) {
                wife=new Wife();
            }
        }
    }
    return wife;
}

}


#### 静态内部类
`volatile`关键字在老版本中JDK是无法正常工作的。这种静态内部类的方式,利用了JVM自身的机制来保证线程安全。因为`WifeHloder`是私有的,除了getWife()之外没有其他方式可以访问实例对象,而且只有在调用`getWife()`时才会真正创建实例对象
java

public class Wife {
private static class WifeHolder {
private static final Wife wife = new Wife();
}

private Wife() {

}

public static Wife getWife() {
    return WifeHolder.wife;
}

}


#### 枚举
代码很是简单,可以通过`Wife.INSTANCE`来访问对象,这比`getWife()`简单得多,而且创建枚举默认就是线程安全的,还可以防止反序列化带来的问题
java
public enum Wife {
INSTANCE;
// 自定义的其他任何方法
public void whateverMethod() {

}

}
“`

单利模式的应用

当你只需要一个实例对象的时候,就可以考虑使用单例模式。比如在资源共享的情况下,避免由于多个资源操作导致的性能或损耗等,就可以使用单例模式。Config类里面就是使用的单例模式?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值