Java实践之路(设计模式)——单例模式(Singleton)(更新)

本文详细介绍了Java中的单例模式,包括内部类和枚举两种实现方式。通过测试代码展示了这两种实现的线程安全和单例特性,并对两者的优缺点进行了总结对比。枚举实现被推荐为最佳实践,尤其适用于JDK 1.5及以上版本。
摘要由CSDN通过智能技术生成

背景

以前写过单例模式的文章(http://blog.csdn.net/cyxlzzs/article/details/7078548),这里根据最新的理解重新写一下单例模式的设计,主要写两种我认为最好的实现方式

单例模式之内部类实现

这里直接先上代码,后面总结

class RepositoryClass{
    private static class RepositoryClassHolder{
        private static RepositoryClass instance = new RepositoryClass();
    }

    private RepositoryClass(){
        System.out.println("RepositoryClass constructor");
    }

    public static RepositoryClass getInstance(){
        return RepositoryClassHolder.instance;
    }
}

这里定义了一个数据仓库类

单例模式之枚举实现

也是先上代码

enum RepositoryEnum{
    INSTANCE;           //单例对象

    private RepositoryEnum(){
        System.out.println("RepositoryEnum constructor");
    }

    public static RepositoryEnum getInstance(){
        return INSTANCE;
    }
}

该枚举的作用和上面的仓库类是一样的

测试代码

    public static void main(String[] args){
        List<RepositoryClass> intances1 = new CopyOnWriteArrayList<>();
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                RepositoryClass instance = RepositoryClass.getInstance();
                intances1.add(instance);
            }, "t"+String.valueOf(i)).start();
        }

        List<RepositoryEnum> intances2 = new CopyOnWriteArrayList<>();

        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                RepositoryEnum instance = RepositoryEnum.getInstance();
                intances2.add(instance);
            }, "t"+String.valueOf(i)).start();
        }

        while(Thread.activeCount()>1){
            Thread.yield();
        }

        System.out.println("==============");
        intances1.forEach(System.out::println);
        System.out.println("==============");
        intances2.forEach(System.out::println);
    }

输出结果

RepositoryClass constructor
RepositoryEnum constructor
==============
RepositoryClass@5fd0d5ae
RepositoryClass@5fd0d5ae
RepositoryClass@5fd0d5ae
RepositoryClass@5fd0d5ae
RepositoryClass@5fd0d5ae
RepositoryClass@5fd0d5ae
RepositoryClass@5fd0d5ae
RepositoryClass@5fd0d5ae
RepositoryClass@5fd0d5ae
RepositoryClass@5fd0d5ae
==============
instance
instance
instance
instance
instance
instance
instance
instance
instance
instance

两种方式都适用了10个线程来进行获取对象实例并将实例放到list中,从结果可以看到,两种方式的构造方法都只执行了一次,而且对象实例list中的对象是相同的

总结对比

1、内部类实现的单例模式优点在于:懒加载,效率高,线程安全;缺点在于有些机制还是会破坏单例,比如序列化,反射和clone,当然可以有相应的机制来防止这些,可以在网上查一下解决的方法

2、枚举实现是jdk版本1.5以上才有的,但这种方式是实现单例模式的最好方式,推荐使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值