Java单例模式的5种实现方法
单例模式有5种实现方式:饿汉、懒汉、双重校验锁、静态内部类和枚举
饿汉
类加载的时候就创建了实例
优点:类加载的时候创建一次实例,避免了多线程同步问题
缺点:即使单例没被用到也会创建,浪费内存
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() { }
public static Singleton getInstance() {
return instance;
}
}
饿汉-变种
public class Singleton {
private static Singleton instance = null;
static {
instance = new Singleton();
}
private Singleton() { }
public static Singleton getInstance() {
return this.instance;
}
}
懒汉-(非线程安全)
优点:需要时才去创建
缺点:没有考虑线程安全问题,多个线程并发调用getInstance,可能会创建多个实例
public class Singleton {
private static Singleton instance = null;
private Singleton() { }
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
懒汉-(线程安全)
缺点:性能问题,添加了synchronized的函数比一般方法慢得多,若多次调用getInstance,则累积的性能损耗特别大。
public class Singleton {
private static Singleton instance = null;
private Singleton() { }
public static Synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
双重校验锁
大部分情况下,同步代码块都不会执行到,提高了程序的性能。
有一种情况,两个线程ThreadA,ThreadB,如果threadA执行到了第一个if条件判断,instance = null;ThreadB也执行到了if条件判断instance = null,所以A和B会依次执行同步代码块里的代码。为了避免创建两个实例,因此又在同步代码块里添加了if条件进行二重检验。
public class Singleton {
private static Singleton instance = null;
private Singleton() { }
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
静态内部类
public class StaticSingleton {
private StaticSingleton() {}
private static class SingletonHolder {
private static StaticSingleton INSTANCE = new StaticSingleton();
}
public static getInstance() {
return SingletonHolder.INSTANCE;
}
}
枚举
public enum Singleton {
INSTANCE;
public void xx(){
}