创建型设计模式之单例模式


单例模式使用场景:
需要频繁和创建和销毁的对象
创建对象耗时过多或消耗资源过多,即重量级对象,但又经常用到的对象
工具类对象,频繁访问数据库或文件的对象(如数据源、session工厂等)
Runtime就是精典的饿汉单例模式应用
public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    /**
     * Returns the runtime object associated with the current Java application.
     * Most of the methods of class <code>Runtime</code> are instance
     * methods and must be invoked with respect to the current runtime object.
     *
     * @return  the <code>Runtime</code> object associated with the current
     *          Java application.
     */
    public static Runtime getRuntime() {
        return currentRuntime;
    }

    /** Don't let anyone else instantiate this class */
    private Runtime() {}

public static void main(String[] args) {
   //精典的饿汉模式
  Runtime.getRuntime();

Singleton s1 = Singleton.Instance;
Singleton s2= Singleton.Instance;
System.out.println(s1==s2);
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
s1.sayHello();
}

 

/**
 * 饿汉式(静态变量)
 * 优点:写法简单,在类装载时完成实例化,避免了线程同步问题
 * 缺点:装载时完成实例化,没有达到懒加载效果,如果不使用这个实例,造成内存浪费。
 * 结论:可用,会造成内存浪费。
 */
public class Singleton {

    //1. 构造器私有化,外部不能new
    private  Singleton(){

    }

    //2. 内部创建实类对象
    private final static Singleton instance = new Singleton();

    //3. 对外提供静态方法,返回对象实例
    public static Singleton getInstance(){
        return instance;
    }
}

/**
 * 饿汉式(静态代码块)
 * 优点:写法简单,在类装载时完成实例化,避免了线程同步问题
 * 缺点:装载时完成实例化,没有达到懒加载效果,如果不使用这个实例,造成内存浪费。
 * 结论:可用,会造成内存浪费。
 */
public class Singleton {

    //1. 构造器私有化,外部不能new
    private  Singleton(){

    }

    //2. 静态代码块中创建实类对象
    private final static singleton.type2.Singleton instance;
    static{
        instance = new singleton.type2.Singleton();
    }

    //3. 对外提供静态方法,返回对象实例
    public static singleton.type2.Singleton getInstance(){
        return instance;
    }
}
/**
 * 懒汉式(线程不安全)
 * 只能在单线程下使用
 */
public class Singleton {
    private Singleton(){};

    private static Singleton instance;

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


/**
 * 懒汉式(同步方法解决线程安全)
 * 效率低
 */
public class Singleton {
    private static Singleton instance;
    private Singleton(){};
    public static synchronized Singleton getInstance(){
        if(instance==null){
            instance=new Singleton();
        }
        return instance;
    }
}

/**
 * 同步代码块解决线程安全
 * 不推荐
 */
public class Singleton {
    private static Singleton instance;
    private Singleton(){};
    public static Singleton getInstance(){
        if(instance==null){
            synchronized (Singleton.class){
                instance=new Singleton();
            }
        }
        return instance;
    }
}
/**
 * 双重检查
 * 线程安全,延迟加载,效率较高
 * 推荐使用

 双重校验锁法会有怎样的情景:
 * STEP 1. 线程A访问getInstance()方法,因为单例还没有实例化,所以进入了锁定块。
 * STEP 2. 线程B访问getInstance()方法,因为单例还没有实例化,得以访问接下来代码块,而接下来代码块已经被线程1锁定。
 * STEP 3. 线程A进入下一判断,因为单例还没有实例化,所以进行单例实例化,成功实例化后退出代码块,解除锁定。
 * STEP 4. 线程B进入接下来代码块,锁定线程,进入下一判断,因为已经实例化,退出代码块,解除锁定。
 * STEP 5. 线程A初始化并获取到了单例实例并返回,线程B获取了在线程A中初始化的单例。
 * 理论上双重校验锁法是线程安全的,并且,这种方法实现了lazyloading。
 */
public class Singleton {
    private static volatile Singleton instance;
    private Singleton(){};
    public static Singleton getInstance(){
        if(instance==null){
            synchronized (Singleton.class){
                if(instance==null){
                    instance=new Singleton();
                }
            }
        }
        return instance;
    }
}

/**
 * 静态内部类不会在单例加载时就加载,而是在调用getInstance()方法时才进行加载,
 * 达到了类似懒汉模式的效果, *而这种方法又是线程安全的。
 */
public class Singleton {

    private static class SingletonInstantce{
        private final static Singleton instance = new Singleton();
    }

    private Singleton(){

    }

    public static Singleton getInstance(){
        return SingletonInstantce.instance;
    }
}

/**
 * 枚举法
 */
public enum Singleton {
    Instance;
    public void sayHello(){
        System.out.println("hello");
    }
}

 

posted @ 2021-03-05 16:49  黄忠  阅读(81)  评论(0编辑  收藏  举报