几种单例模式的实现

1.饿汉式html

public class Singleton        
{        
    private static Singleton instance = new Singleton();        
    private Singleton(){        
        …        
    }        
    public static Singleton getInstance(){        
             return instance;         
    }        
}

缺点:第一次加载类的时候会连带着建立Singleton实例,这样的结果与咱们所指望的不一样,由于建立实例的时候可能并非咱们须要这个实例的时候。同时若是这个Singleton实例的建立很是消耗系统资源,而应用始终都没有使用Singleton实例,那么建立Singleton消耗的系统资源就被白白浪费了。安全

 

2.懒汉式多线程

public class Singleton{        
    private static Singleton instance = null;        
    private Singleton(){        
        …        
    }        
    public static Singleton getInstance(){        
        if (instance == null)        
            instance = new Singleton();         
                return instance;         
    }        
}

缺点:存在多线程并发问题,并发下可能建立多个对象。并发

3.解决并发问题函数

方法上使用Class锁机制线程

public static synchronized Singleton getInstance(){        
    if (instance == null)        
    instance = new Singleton();         
    return instance;         
}

缺点:加载方法上锁粒度太大,影响并发。实际上当单例实例被建立之后,其后的请求没有必要再使用互斥机制了。htm

用double-checked locking将锁缩减至代码块级别对象

public static Singleton getInstance(){        
    if (instance == null)        
        synchronized(instance){        
            if(instance == null)        
                instance = new Singleton();        
        }        
    return instance;         
}

 对于JVM而言,它执行的是一个个Java指令。在Java指令中建立对象和赋值操做是分开进行的,也就是说instance = new Singleton();语句是分两步执行的。可是JVM并不保证这两个操做的前后顺序,也就是说有可能JVM会为新的Singleton实例分配空间,而后直接赋值给instance成员,而后再去初始化这个Singleton实例。这样就使出错成为了可能。blog

使用volatile防止重排序:排序

public class Singleton{        
    private static volatile Singleton instance = null;        
    private Singleton(){ … }        
    public static Singleton getInstance(){
        if (instance == null) 
            synchronized(instance){ 
                if(instance == null) 
                    instance = new Singleton();
    }
    return instance;      
}

 

不加锁:为了实现慢加载,而且不但愿每次调用getInstance时都必须互斥执行。

public class Singleton{        
    private Singleton(){        
        …        
    }        
    private static class SingletonContainer{        
        private static Singleton instance = new Singleton();        
    }        
    public static Singleton getInstance(){        
        return SingletonContainer.instance;        
    }        
}

JVM内部的机制可以保证当一个类被加载的时候,这个类的加载过程是线程互斥的。这样当咱们第一次调用getInstance的时候,JVM可以帮咱们保证instance只被建立一次,而且会保证把赋值给instance的内存初始化完毕,这样咱们就不用担忧3.2中的问题。此外该方法也只会在第一次调用的时候使用互斥机制,这样就解决了3.1中的低效问题。最后instance是在第一次加载SingletonContainer类时被建立的,而SingletonContainer类则在调用getInstance方法的时候才会被加载,所以也实现了惰性加载。

 

https://www.cnblogs.com/jingpeipei/p/5771716.html

 

/** 推荐
 * 静态内部类实现单例模式(懒加载的一种)
 * 静态内部类只有在调用的时候才初始化,而且初始化过程线程安全。
 * instance不提供修改实例方法,静态变量只初始化一次,因此final修饰不加也同样。
 * 兼备了并发高效调用和懒加载的优点。
 * 结论:线程安全,调用效率高,而且能够延时加载。
 */
public class StaticClassSingleton {
    //私有构造函数
    private StaticClassSingleton(){};

    //静态内部类
    private static class SingletonClassInstance{
        private static final StaticClassSingleton INSTANCE =
                new StaticClassSingleton();
    }

    //提供实例的调用方法
    public static StaticClassSingleton getInstance(){
        return SingletonClassInstance.INSTANCE;
    }
}

/** 推荐
 * 枚举类对象自己就是一个单例对象。
 * 没有延时加载的特性。
 * 能够自然的防止反射和反序列化的漏洞,由于枚举是基于JVM底层实现的。
 * 结论:线程安全,调用效率高,可是不是延时加载,自然防止反射和反序列化漏洞。
 */
public enum  EnumSingleton {
    /**
     * 枚举对象
     */
    INSTANCE;

    /**      * 成员方法      */     public void singletonOperation(){         //单例对象的其它操做实现。     } }  

相关文章
相关标签/搜索