1.单例模式

单例模式介绍:

Ensure a class has only one instance,and provide a global point of access to it.(确保一个类只有一个实例,向整个系统提供这个实例。)

单例模式优点:

  1. 单例模式在内存中只有一个实例,减少内存开支;
  2. 省去了频繁的实例化对象,减轻了GC压力;
  3. 单例模式可在系统设置全局访问点,优化和共享资源访问。

单例模式缺点:

  1. 扩展困难,单例模式一般没有接口,若要扩展,除了修改代码基本没有第二种途径实现;
  2. 与单一职责原则冲突,一个类应该只实现一个逻辑,而不关心其是否为单例的,是不是单例取决于环境,单例模式把 要单例 和业务逻辑融合在一个类中。

单例模式使用场景:

  1. 要求生成唯一序列号环境;
  2. 在项目中需要一个共享访问点或共享数据,比如一个Web页面上的计数器,使用单例模式保持计数器的值,并确保是线程安全的;
  3. 创建一个对象需要消耗的资源过多,例如访问IO和数据库资源;
  4. 需要定义大量工具类。

单例模式代码:

方式1

在加载类时初始化对象

public class Singleton1 {

    public static final Singleton1 singleton1 = new Singleton1();//初始化一个对象

    private Singleton1() {
    }

    public static Singleton1 getInstance() {
        return singleton1;
    }

    public String toString() {
        return "Singleton1{}";
    }
}

方式2

通过枚举实现

public enum Singleton2 {

    INSTANCE;
    @Override
    public String toString() {
        return "Singleton2{}";
    }
}

方式3

懒加载方式,在使用时实例化对象

public class Singleton3 {

    //使用volatile关键字,使INSTANCE参数在改变时内存可见
    private static volatile Singleton3 INSTANCE;

    public static Singleton3 getInstance() {
        Singleton3 result = INSTANCE;
        if (result == null) {
            synchronized (Singleton3.class) {//加锁防止线程竞争导致实例化多个对象
                result = INSTANCE;
                if (result == null) {//再次判断类是否实例化
                    INSTANCE = result = new Singleton3();
                }
            }
        }
        return result;
    }

    public String toString() {
        return "Singleton3{}";
    }
}

在加载单例类之后单例对象是否会被JVM回收

测试代码:

    @Test
    public void test2() {
        System.out.println(Singleton1.getInstance().toString());
        while (true) {
            byte[] a = new byte[3 * 1024 * 1024];
        }
    }

在加载完单例类之后,通过不断实例化对象时JVM对内存进行回收。
jdk版本:1.8.0_66
vm参数:-verbose:gc -Xms20M -Xmx20M(每次jvm进行垃圾回收时显示内存信息,JVM内存固定设置为20M)
运行结果:

Singleton1{}
[GC (Allocation Failure)  5017K->1255K(19840K), 0.0026116 secs]
[GC (Allocation Failure)  4327K->1254K(19840K), 0.0015265 secs]
[GC (Allocation Failure)  4326K->1254K(19840K), 0.0002786 secs]
[GC (Allocation Failure)  4326K->1254K(19840K), 0.0002693 secs]

每次回收内存在3M,故垃圾回收没有回收单例对象。

单例对象为什么不被回收?

目前JVM虚拟机垃圾收集算法使用根搜索算法;所以,如果从根开始搜索,经过一些列的路径,可以到达java堆中的对象,那么这个对象就是活的。
根对象有:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象;
- 方法区中类的静态属性引用的对象;
- 方法区中的常量引用的对象;
- 本地方法栈中JNI的引用的对象。
单例模式中对象被方法区中类的静态属性所引用,故不被回收。

既然单例对象不会被垃圾回收,但单例类本身如果长时间不使用会不会被收集呢?

JVM卸载类的判断条件如下:
- 该类所有的实例都被回收,java堆中不存在该类任何实例;
- 加载该类的ClassLoader已经被回收;
- 该类对应的java.lang.Class对象没有任何地方被引用,在任何地方没有通过反射访问该类的方法。
单例类不满足条件1,故不会被回收。

参考资料:
设计模式之禅(第2版).pdf
http://www.importnew.com/15527.html

源码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值