Java编写单例类的几种方式

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、线程安全。且不用加锁。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章