一、什么是单例模式
单例模式就是在整个软件系统中,只允许存在一个类的实例的设计模式。
二、单例模式的两种实现方式
为了保证一个类中只有一个类的实例,自然而然地就想到了 static 关键字,static 就是保证一个类全局只有一个某种变量或函数。
2.1 饿汉式
饿汉式就是在类加载的时候就创建一个静态的类的实例放在方法区中,当有线程要使用这个类的实例时,通过某个方法来获得这个静态实例。
public class SingleModel {
//类的实例时静态变量,全局只有一个
private static SingleModel singleModel = new SingleModel();
//构造函数一定要是 private 的,不然每当调用 new 的时候,就一定会创建一个对象
private SingleModel(){}
//通过静态函数来获得类的实例,public 的
public static SingleModel getSingleModel() {
return singleModel;
}
}
2.2 懒汉式
懒汉式是当有线程通过方法获得类的实例得时候才创建一个返回。
public class SingleModel {
private static SingleModel singleModel = null;
private SingleModel(){}
public static SingleModel getSingleModel() {
if(singleModel == null) {
singleModel = new SingleModel();
}
return singleModel;
}
}
三、两种模式的对比
饿汉式在类加载的时候就创建了一个对象到内存中,并且一直保留,如果一直没有线程要使用这个这个对象,那么就白白的浪费了内存。
懒汉式避免了饿汉式的问题,但是会导致线程不安全:如果两个线程在很短的时间间隔内调用了 getSingleMode() 方法,第一个线程判断 singleModel == null 返回 true,这时方法里准备创建对象,然而,就在它创建对象的时候,第二个线程进来了,它也判断 singleModel == null 返回了 true,这时它也要创建,那么第一个线程创建的实例就被第二个线程覆盖掉了。
解决懒汉式线程不安全:
public class SingleModel {
private static SingleModel singleModel;
private SingleModel() {
}
public static SingleModel getModel() {
if(singleModel == null) { //在这里加一步判断可以提高效率,因为当 singleClass 已经被实例化之后线程就不用阻塞了
synchronized (SingleModel.class) {
if(singleModel == null) {
singleModel = new SingleModel();
}
}
}
return singleModel;
}
}