浅谈单例模式 饿汉式 懒汉式 1.双重检查改良版 2.holder方式 3.枚举法

package com.dwz.concurrency2.chapter1;
/**
 * 饿汉式
 */
public class SingletonObject2 {
    /*
     * can't lazy load.
     */
    private static final SingletonObject2 instance = new SingletonObject2();
    
    private SingletonObject2() {
        //empty
    }
    
    public static SingletonObject2 getInstance() {
        return instance;
    }
}

缺点:不能进行懒加载,可能会造成资源浪费

懒汉式

package com.dwz.concurrency2.chapter1;
/**
 * 懒汉式(双重检查)
 */
public class SingletonObject1 {
    private static SingletonObject1 instance;
    
    private SingletonObject1() {
        //empty
    }
    
    //double check
    //解决了懒加载问题和线程安全问题
    public static SingletonObject1 getInstance() {
        if(null == instance) {
            synchronized (SingletonObject1.class) {
                if(null == instance) {
                    instance = new SingletonObject1();
                }
            }
        }
        //会出现初始化异常问题,instance还在重排序,未初始化完成,此时已不是null,就被return
        return instance;
    }
}

缺点:不能保证线程绝对安全,尤其是new SingletonObject1()中加载比较重的v资源时

介绍三种比较优雅的v单例模式:

1.双重检查改良版

package com.dwz.concurrency2.chapter1;
/**
 * 懒汉式(双重检查-线程安全)
 */
public class SingletonObject3 {
    //volatile可以保证内存可见性,有序性,不让jvm自作主张去优化
    //可以保证之前的写操作完成
    private static volatile SingletonObject3 instance;
    
    private SingletonObject3() {
        //empty
    }
    
    //double check add volatile
    public static SingletonObject3 getInstance() {
        if(null == instance) {
            synchronized (SingletonObject3.class) {
                if(null == instance) {
                    instance = new SingletonObject3();
                }
            }
        }
        return instance;
    }
}

缺点:虽然解决了线程安全问题,但是jvm的一些底层优化操作被摒弃

2.holder方式

package com.dwz.concurrency2.chapter1;
/**
 * holder方式(推荐使用)
 * 懒加载、线程安全、效率高
 */
public class SingletonObject4 {
    
    private SingletonObject4() {
        
    }
    
    private static class InstanceHolder {
        private final static SingletonObject4 instance = new SingletonObject4();
    }
    
    public static SingletonObject4 getInstance() {
        return InstanceHolder.instance;
    }
}

3.枚举法

package com.dwz.concurrency2.chapter1;

import java.util.stream.IntStream;

/**
 * 枚举法:(大师推荐)
 * 天生就是线程安全的,构造函数只被加载一次
 */
public class SingletonObject5 {
    
    private SingletonObject5() {
        
    }
    
    private enum Singleton {
        INSTANCE;
        
        private final SingletonObject5 instance;
        
        Singleton() {
            instance = new SingletonObject5();
        }
        
        public SingletonObject5 getInstance() {
            return instance;
        }
    }
    
    public static SingletonObject5 getInstance() {
        return Singleton.INSTANCE.getInstance();
    }
    
    public static void main(String[] args) {
        IntStream.rangeClosed(1, 100)
                 .forEach(i-> new Thread(String.valueOf(i)) {
                     @Override
                    public void run() {
                         System.out.println(SingletonObject5.getInstance());
                    }
                 }.start());
    }
}