文章内容
一、饿汉模式
//饥饿模式
public final class EagerSingleton {
private static EagerSingleton singObj = new EagerSingleton();
private EagerSingleton() {
}
public static EagerSingleton getSingleInstance() {
return singObj;
}
}
性能问题:每个对象在没有使用之前就已经初始化了,如果这个对象很大呢?没有使用这个对象之前,就把它加载到了内存中去是一种巨大的浪费
二、懒汉模式
1、写法一
//懒汉模式
public final class LazySingleton {
private static LazySingleton singObj = null;
private LazySingleton() {
}
public static LazySingleton getSingleInstance() {
if (null == singObj ) {
singObj = new LazySingleton();
}
return singObj;
}
}
性能问题:线程不安全,多个线程可能同时运行判断singObj为null,于是同时进行了初始化
2、写法二
//懒汉模式加Synchronized
public final class ThreadSafeSingleton {
private static ThreadSafeSingleton singObj = null;
private ThreadSafeSingleton() {
}
public static Synchronized ThreadSafeSingleton getSingleInstance() {
if(null == singObj ) {
singObj = new ThreadSafeSingleton();
}
return singObj;
}
}
性能问题:同步的代价必然会一定程度的使程序的并发度降低
3、写法三
//双重检查锁
public final class DoubleCheckedSingleton {
private static DoubleCheckedSingletonsingObj = null;
private DoubleCheckedSingleton() {
}
public static DoubleCheckedSingleton getSingleInstance() {
if (null == singObj ) {
Synchronized(DoubleCheckedSingleton.class) {
if(null == singObj) {
singObj = new DoubleCheckedSingleton();
}
}
}
return singObj;
}
}
优点:这种写法使得只有在加载新的对象进行同步,在加载完了之后,其他线程就可以判断跳过锁的的代价,做到很好的并发度
4、写法四
//Initialization on Demand Holder
public class Singleton {
private static class SingletonHolder {
public final static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
优点: 这种方法使用内部类来做到延迟加载对象,在初始化这个内部类的时候,JLS(Java Language Sepcification)会保证这个类的线程安全。这种写法最大的美在于,完全使用了Java虚拟机的机制进行同步保证,没有一个同步的关键字
三、防止序列化破坏单例模式
//添加这个hook函数,那么系统在反序列化的过程中就会通过该Hook方法得到原有的单例,而不是重新创建一个单例。
private Object readResolve() throws ObjectStreamException {
return singleton;
}