场景
在学习Mybatis或者Hibernate中,有一个SqlSessionFactory对象。此对象属于重量级对象,消耗的资源比较大,也只需要存在一个即可。类似的对象还有,线程池、缓存、日志等。这种情况下,就可以使用单例模式来进行控制对象的创建,确保只存在一个。
饿汉模式
懒汉的的单例模式顾名思义就是,在使用前就已经完成的初始化。
代码:
public class HungrySingleton {
//类装载时就完成初始化
private static HungrySingleton hungrySingleton = new HungrySingleton();
//申明私有的构造方法,无法外部通过new初始化对象
private HungrySingleton() {
}
public static HungrySingleton getSingleton() {
System.out.println("获取单例对象");
return HungrySingleton.hungrySingleton;
}
}
这样的写法很简单,但由于在类装载时就完成了初始化,可能会造成一定的资源浪费,但是不存在多线程的问题,比较常见。
懒汉模式
饿汉模式是在类装载的时候就完成了初始化,懒汉模式在被调用的时候才进行初始化,不会造成内存的浪费问题。
代码:
public class LazySingleton {
private static LazySingleton lazySingleton;
//申明私有的构造方法,无法外部通过new初始化对象
private LazySingleton() {
}
public static LazySingleton getLazySingleton() {
//多线程中,可能出现问题,导致多次初始化
if (lazySingleton == null) {
System.out.println("完成懒汉加载");
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
在多线程中,一个线程准备创建一个对象,这时另一个线程进入if条件判断中,此时对象还未创建,两个线程都将创建对象。
懒汉—Version2.0
public class LazySingleton {
private static LazySingleton lazySingleton;
//申明私有的构造方法,无法外部通过new初始化对象
private LazySingleton() {
}
//同步
public static synchronized LazySingleton getLazySingleton() {
if (lazySingleton == null) {
System.out.println("完成懒汉加载");
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
一整个方法加上synchronized 进行同步,对性能而言会存在很大的问题,再进一步改进。
懒汉—Version3.0
public class LazySingleton {
private static LazySingleton lazySingleton;
//申明私有的构造方法,无法外部通过new初始化对象
private LazySingleton() {
}
//同步
public static synchronized LazySingleton getLazySingleton() {
if (lazySingleton == null) {
synchronized (LazySingleton.class) {
if (lazySingleton == null) {
System.out.println("完成懒汉加载");
lazySingleton = new LazySingleton();
}
}
}
return lazySingleton;
}
}
需要对对象进行双重检查才能保证在多线程下,不会创建多个对象。