码迷,mamicode.com
首页 > 其他好文 > 详细

四种单例写法与测试

时间:2020-06-14 11:16:49      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:inline   设计   业务   data-   ext   The   csdn   splay   pad   

四种单例写法与测试

本文主要实现了四种方式的单例模式与测试,双重检测代码稍微麻烦点。每一个类都设有一个测试方法,可以替换自己需要做的一些业务。

各种方式需要注意的点

  1. 饿汉式
    • 私有化构造函数
    • final定义instance
  2. 双重检测
    • 私有化构造函数
    • volatile修饰instance,否则会可能得到未初始化的实例
    • 可替换为其他非静态实例使用
  3. 静态内部类
    • 私有化构造函数
    • 只能静态实例
  4. 枚举
    • 不用构造函数
    • 可定义多个枚举,如:enum{ IN1, INS2 }则实现多例
    • 保证线程安全,唯一不会被反射和序列化影响的单例模式

参考:
你知道吗?枚举单例模式是世界上最好的单例模式
《java 并发编程的艺术》
《effective java》

以下是代码:

import java.util.concurrent.atomic.AtomicLong;


public class Singleton {
    public static void main(String[] args) {
        //测试饿汉式
        HungrySingleton h1 = HungrySingleton.getInstance();
        HungrySingleton h2 = HungrySingleton.getInstance();
        System.out.println("两个实例是否相等:" + (h1 == h2));
        System.out.println("第一次加" + h1.getId());
        System.out.println("第二次加" + h2.getId());

        System.out.println("------------------------------------");
        //测试双重检测
        DoubleCheckSingleton d1 = DoubleCheckSingleton.getInstance();
        DoubleCheckSingleton d2 = DoubleCheckSingleton.getInstance();
        System.out.println("两个实例是否相等:" + (d1 == d2));
        System.out.println("第一次加" + d1.getId());
        System.out.println("第二次加" + d2.getId());

        System.out.println("------------------------------------");
        //测试静态内部类
        StatiInnerClassSingleton s1 = StatiInnerClassSingleton.getInstance();
        StatiInnerClassSingleton s2 = StatiInnerClassSingleton.getInstance();
        System.out.println("两个实例是否相等:" + (s1 == s2));
        System.out.println("第一次加" + s1.getId());
        System.out.println("第二次加" + s2.getId());

        System.out.println("------------------------------------");
        //测试枚举
        EnumSingleton e1 = EnumSingleton.INSTANCE;
        EnumSingleton e2 = EnumSingleton.INSTANCE;
        System.out.println("两个实例是否相等:" + (e1 == e2));
        System.out.println("第一次加" + e1.getId());
        System.out.println("第二次加" + e2.getId());
    }

}

/**
 * 饿汉式
 */
class HungrySingleton{
    private static final HungrySingleton instance = new HungrySingleton();
    private HungrySingleton(){}

    public static HungrySingleton getInstance(){
        return instance;
    }

    //用于测试单例正确性
    private AtomicLong id = new AtomicLong(0);
    public long getId() {
        return id.incrementAndGet();
    }
}

/**
 * 双重检测
 */
class DoubleCheckSingleton{
    private static volatile DoubleCheckSingleton instance = null;
    private DoubleCheckSingleton(){}

    public static DoubleCheckSingleton getInstance(){
        if(instance == null){
            synchronized (DoubleCheckSingleton.class){
                if(instance == null){
                    instance = new DoubleCheckSingleton();
                }
            }
        }
        return instance;
    }

    //用于测试单例正确性
    private AtomicLong id = new AtomicLong(0);
    public long getId() {
        return id.incrementAndGet();
    }
}


/**
 * 静态内部类
 */
class StatiInnerClassSingleton{
    private StatiInnerClassSingleton(){}

    private static class InstanceHolder{
        public static StatiInnerClassSingleton instance = new StatiInnerClassSingleton();
    }

    public static StatiInnerClassSingleton getInstance(){
        return InstanceHolder.instance;
    }

    //用于测试单例正确性
    private AtomicLong id = new AtomicLong(0);
    public long getId() {
        return id.incrementAndGet();
    }
}


/**
 * 枚举
 */
enum EnumSingleton{
    INSTANCE;

    //用于测试单例正确性
    private AtomicLong id = new AtomicLong(0);
    public long getId() {
        return id.incrementAndGet();
    }
}

四种单例写法与测试

标签:inline   设计   业务   data-   ext   The   csdn   splay   pad   

原文地址:https://www.cnblogs.com/muche-moqi/p/13123861.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!