多线程安全的单例模式进阶

package com.MySingletonTest;

/**
 * Created by liuxuanjie on 2020/01/08.
 * 单例模式的创建,保证多线程安全
 *
 * ps:
 *  这是第一种方式,直接在类加载的时候创建一次
 */
public class MySingleton1
{
    //私有静态自身引用
    private static MySingleton1 singleton = new MySingleton1();

    //私有构造方法
    private MySingleton1() {
    }

    //静态外部调用入口
    public static MySingleton1 getSingleton()
    {
        return singleton;
    }
}
package com.MySingletonTest;

/**
 * Created by liuxuanjie on 2020.1.8.
 * 单例模式的实现,保证多线程的线程安全
 *
 * ps:
 *  跟第一种方式一样,只是写法不同
 *  仍旧利用的是类加载器的单一性加载
 */
public class MySingleton2 {
    private static MySingleton2 singleton = null;

    //静态代码段,类加载时期会执行一次
    static
    {
        singleton = new MySingleton2();
    }

    //私有构造方法
    private MySingleton2()
    {
    }

    //静态外部入口
    public static MySingleton2 getSingleton()
    {
        return singleton;
    }
}
package com.MySingletonTest;

/**
 * Created by liuxuanjie on 2020.1.8.
 * 单例模式的实现,保证多线程安全
 *
 *  ps
 *      采用静态内部类的方法
 *      这种方法对前两种方法做出了优化
 *      实现了,真正用的时候才真正实例化
 *
 *  解释说明:
 *  1. 外部类初次加载,会初始化静态变量、静态代码块、静态方法,但不会加载内部类和静态内部类。
 *  2. 实例化外部类,调用外部类的静态方法、静态变量,则外部类必须先进行加载,但只加载一次。
 *  3. 直接调用静态内部类时,外部类不会加载。
 */
public class MySingleton3
{
    //私有静态内部类
    private static class InnerSingletonHold
    {
        private static MySingleton3 singleton = new MySingleton3();
    }

    //私有静态方法
    private MySingleton3()
    {
    }

    public static MySingleton3 getSingleton()
    {
        return InnerSingletonHold.singleton;
    }
}
package com.MySingletonTest;

import java.util.concurrent.atomic.AtomicReference;

/**
 * Created by liuxuanjie on 2020.1.8.
 * 实现单例模式,保证多线程安全
 *
 * ps:
 *  使用CAS方法,实现原子性操作
 */
public class MySingleton4
{
    /**
     * 原子引用
     * 使用java的并发包下的的atomic操作。
     */
    private static AtomicReference<MySingleton4> atomicReference = new AtomicReference<>();


    /**
     * 私有构造方法
     */
    private MySingleton4()
    {
    }


    /**
     * CAS操作实现单例模式下的多线程安全
     * ps:
     *  优点:就是CAS操作的优点,自旋无阻塞
     *  缺点:消耗CPU,并且在实例化那一行代码会有很多无用实例化对象
     *  可以理解为,很多实例化对象被创建,只不过CAS操作的结果是只保留一个
     *
     * @return 单例模式唯一真实引用
     */
    public static MySingleton4 getSingleton()
    {
        //CAS操作一般配合无限循环进行自旋
        while(true)
        {
            //先获得当前的状态
            MySingleton4 singleton = atomicReference.get();

            //如果当前状态不为空,证明单例已经实例化,直接返回
            if (null != singleton)
            {
                return singleton;
            }
            else
            {
                //单例引用为空,实例化
                singleton = new MySingleton4();

                //CAS原子性操作,更新引用,指向实例化对象
                //此刻发生竞争,有且只能有一个线程更新成功
                if (atomicReference.compareAndSet(null, singleton))
                {
                    return singleton;
                }
            }
        }
    }
}
package com.MySingletonTest;

/**
 * Created by liuxuanjie on 2020.1.8.
 * 实现单例模式,保证多线程安全
 *
 * ps:
 *  这个方法也比较常见,双判断减少Synchronized的性能消耗
 */
public class MySingleton5
{
    /**
     * 私有静态的自身引用
     */
    private volatile static MySingleton5 singleton = null;


    /**
     * 私有构造方法
     */
    private MySingleton5()
    {
    }


    /**
     * 双判断减少synchronized的作用次数,以此减少性能消耗
     * @return 单例模式的唯一真实实例化对象的引用
     */
    public static MySingleton5 getSingleton()
    {
        if(singleton == null)
        {
            synchronized (MySingleton5.class)
            {
                if(singleton == null)
                {
                    singleton = new MySingleton5();
                }
            }
        }

        return singleton;
    }
}

猜你喜欢

转载自blog.csdn.net/romantic_jie/article/details/103891855