1.饿汉式
public class HungerySingleton {
//ClassLoader 类加载时立即实例化对象,仅实例化一次,线程安全的
private static HungerySingleton hungerySingleton = new HungerySingleton();
public static HungerySingleton getInstance(){
return hungerySingleton;
}
}
优点:仅实例化一次,线程是安全的。获取实例的速度快
缺点:类加载时立即实例化对象,可能实例化的对象不被使用,造成内存的浪费。
2.懒汉式
public class HoonSingleton {
//不能保证实例对象的唯一性
private static HoonSingleton hoonSingleton = null;
public static HoonSingleton getInstance(){
if(hoonSingleton==null){
hoonSingleton = new HoonSingleton();
}
return hoonSingleton;
}
}
优点:获取实例时才进行实例的初始化,节省系统资源
缺点:1、如果获取实例时,初始化的工作量较多,加载速度会变慢,影响系统系能
2、每次获取实例都要进行非空检查,系统开销大
3、非线程安全。当多个线程同时getInstance()时,可能hoonSingleton实例化未完成,hoonSingleton==null判断均为true,造成对象重复实例化。
3.双重检查锁 DCL(double-checked locking)+ volatile
public class HoonSingleton {
private static volatile HoonSingleton hoonSingleton = null;
// 使用sync同步HoonSingleton.class 两次判断hoonSingleton是否为null 避免并发导致hoonSingleton被重新实例化
// 并没有对整个方法使用sync,锁的粒度变小了,实现了实例对象的唯一性
public static HoonSingleton getInstance(){
if(hoonSingleton==null){
synchronized (HoonSingleton.class) {
if(hoonSingleton==null) {
hoonSingleton = new HoonSingleton();
}
}
}
return hoonSingleton;
}
优点:1、线程安全。注意加粗标记,进行双重检查,保证只在实例未初始化前进行同步,效率高。
2、对hoonSingleton使用volatile修饰符,避免实例化过程中产生的重排序。避免NPE抛出。
缺点:实例非空判断,耗费一定资源
4.Holder方式 广泛使用的一种单例模式
//声明类的时候、成员变量中不声明实例变量,而是放到内部静态类中
public class HolderDemo {
private static class Holder{
private static HolderDemo instance = new HolderDemo();
}
public static HolderDemo getInstance(){
return Holder.instance;
}
}
优点:1、内部类只有在外部类被调用才加载,从而实现了延迟加载
2、线程安全。且不用加锁。