Java单例模式之四种实现

单例模式一:饥饿模式

/**
 * 饥饿模式
 *
 * 不存在并发问题
 * @author davidwang2006@aliyun.com
 * @date 2020/3/6 0006 下午 9:12
 */
public class EagerSingleton {
    private static final EagerSingleton INSTANCE = new EagerSingleton();
    private EagerSingleton(){
        System.out.printf("%s: construct called....%n",getClass().getSimpleName());
    }
    public static EagerSingleton getInstance(){
        return INSTANCE;
    }

    public void sing(){
        System.out.printf("%s: Sing....%n",getClass().getSimpleName());
    }
}

单例模式二:DLC模式

即懒加载模式中的double lock check模式

/**
 * double lock check模式
 * @author davidwang2006@aliyun.com
 * @date 2020/3/6 0006 下午 9:13
 */
public class DoubleLockSingleton {

    //必须使用volatile 是因为cpu有可能指令re-order,
    //此关键字会插入内存屏障,阻止cpu re-order
    private volatile static DoubleLockSingleton INSTANCE = null;
    private DoubleLockSingleton(){
        System.out.printf("%s: construct called....%n",getClass().getSimpleName());
    }

    public static DoubleLockSingleton getInstance(){

        //double check null
        if(INSTANCE == null){
            synchronized (DoubleLockSingleton.class){
                //must check again
                //because maybe another thread initialize it already
                if(INSTANCE == null){
                    INSTANCE = new DoubleLockSingleton();
                }
            }
        }
        return INSTANCE;

    }

    public void sing(){
        System.out.printf("%s: Sing....%n",getClass().getSimpleName());
    }

}

单例模式三:静态内部类模式

优点:不需要double lock check

/**
 * When the singleton class is loaded,
 * inner class is not loaded and hence doesn’t create object when loading the class.
 * Inner class is created only when getInstance() method is called.
 * So it may seem like eager initialization but it is lazy initialization.
 * This is the most widely used approach as it doesn’t use synchronization.
 * @author davidwang2006@aliyun.com
 * @date 2020/3/6 0006 下午 9:16
 */
public class InnerClassSingleton {

    private InnerClassSingleton(){
        System.out.printf("%s: construct called....%n",getClass().getSimpleName());
    }


    private static class Holder{
        static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
    }

    public static InnerClassSingleton getInstance(){
        return Holder.INSTANCE;
    }

    public void sing(){
        System.out.printf("%s: Sing....%n",getClass().getSimpleName());
    }


}

单例模式四:枚举模式

/**
 *
 * 这一种是最好的
 * 比InnerClassSingleton还好一点,因为不用再定义一些不必须的属性和内部类
 *
 * @author davidwang2006@aliyun.com
 * @date 2020/3/6 0006 下午 9:30
 */
public enum EnumSingleton {
    INSTANCE;

    private EnumSingleton(){
        System.out.printf("%s: construct called....%n",getClass().getSimpleName());
    }

    //etc
    private int propertyA;

    //etc....
    public void sing(){
        System.out.printf("%s: Sing....%n",getClass().getSimpleName());
    }

}

 

优劣比较

 

以前四种写法均不存在并发问题,枚举与饥饿模式写法最简便,个人比较推荐枚举模式。

测试类

/**
 * test for singleton
 *
 * java -verbose:class SingletonBoot
 *
 * @author davidwang2006@aliyun.com
 * @date 2020/3/11 0011 上午 11:22
 */
public class SingletonBoot {
    public static void main(String[] args) {
        System.out.printf("%nBEGIN%n%n");

        EagerSingleton.getInstance().sing();
        DoubleLockSingleton.getInstance().sing();
        InnerClassSingleton.getInstance().sing();
        EnumSingleton.INSTANCE.sing();

        System.out.printf("%nEND%n%n");

    }
}

执行结果

BEGIN

[Loaded com.david.learning.concurrent.singleton.EagerSingleton]
[Loaded java.util.Formattable from rt.jar]
EagerSingleton: construct called....
EagerSingleton: Sing....
[Loaded com.david.learning.concurrent.singleton.DoubleLockSingleton]
DoubleLockSingleton: construct called....
DoubleLockSingleton: Sing....
[Loaded com.david.learning.concurrent.singleton.InnerClassSingleton]
[Loaded com.david.learning.concurrent.singleton.InnerClassSingleton$Holder]
InnerClassSingleton: construct called....
InnerClassSingleton: Sing....
[Loaded com.david.learning.concurrent.singleton.EnumSingleton]
EnumSingleton: construct called....
EnumSingleton: Sing....

END

 

澄清

饥饿模式写法与DLC模式相比较并不比DLC耗资源,虽然它是饥饿模式,但其也是在使用这个类的地方才会加载(引用成员或使用方法时初始化)它(变相懒加载)。

 

如有谬误,请各位网友不吝指教。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值