单例模式旨在创建一个唯一的对象,一种恶汉式 一种懒汉式。没什么好说的。但是,在多线程下的情景下 就会出现问题

1、单例模式之恶汉式

/**
 * @author i
 * @create 2019/9/18 20:45
 * @Description 恶汉式
 */
public class Singleton {

    private static Singleton singleton = new Singleton();

    //私有化构造方法
    private Singleton(){

    }

    public static Singleton getInstance(){
        return singleton;
    }
}

1.2、多线程下使用恶汉式创建对象

public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(20);
        for (int i = 0; i < 20 ; i++) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" "+Singleton.getInstance());
                }
            });
        }
    }

1.3、结果:从结果中可以看到 我们使用恶汉式多线程下创建对象是没有问题的。因此 就可以下结论 恶汉式情况下 并发使用不会出现问题, 

2、单例模式之懒汉式

package com.hblg.t1;

/**
 * @author i
 * @create 2019/9/18 20:48
 * @Description 懒汉式单例实现
 */
public class Singleton2 {

    private static Singleton2 instance = null;

    public Singleton2(){

    }

    /***
     * 
     * @return
     */
    public static  Singleton2 getInstance(){
        if(instance == null){
            instance = new Singleton2();   
        }
        return instance;
    }


}

2.1 多线程下使用懒汉式创建对象

ExecutorService threadPool = Executors.newFixedThreadPool(20);
        for (int i = 0; i < 10; i++) {
            threadPool.execute(new Runnable() {

                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" "+Singleton2.getInstance());
                }
            });
        }

        threadPool.shutdown();

2.3 结果 分析 我们可以知道,通过多线程懒汉式创建单例出现了问题,原因是什么呢。

if(instance == null){
    instance = new Singleton2();
}
return instance;

原因就在于此,那就是当多个线程去调用getInstance()方法,由于上面的3行语句 不具有原子性操作,当t1线程进入 第一行

这个时候。线程t2 抢占了cpu执行权获取到了cpu执行时间,去判断时候为空 就会自行创建一个对象。

所有 我们可以通过加锁的方式 来保证数据一致性问题。

/***
     * 双重检测加锁
     * @return
     */
    public static synchronized Singleton2 getInstance(){
        if(instance == null){
            synchronized (Singleton2.class){
                if(instance == null){
                    instance = new Singleton2();   //指令重排序  加vloatile关键字
                }
            }
        }
        return instance;
    }

通过上面 可以解决。