深入理解Java设计模式之单例模式

yizhihongxing

深入理解Java设计模式之单例模式

单例模式是最简单也是最常用的设计模式之一。在实际开发中,经常会遇到需要一个类只能创建一个实例的情况。单例模式保证一个类只有一个实例,并且提供一个全局访问点。本文将深入探讨Java设计模式中的单例模式。

什么是单例模式?

单例模式是指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,一个应用中需要打印日志文件,为了避免多个线程写同一个文件导致文件混乱,可以使用单例模式来保证同一时间只能有一个线程在写文件。

单例模式的特点

单例模式有以下特点:

  • 单例类只有一个实例对象;
  • 该单例对象必须由单例类自行创建,且创建过程只能执行一次;
  • 单例类必须提供一个全局的访问点,让外部代码可以访问该单例对象。

单例模式的实现方式

单例模式有以下两种实现方式:

饿汉式

饿汉式是指在单例类被加载时,就创建唯一的实例对象。这种实现方式比较简单,但是可能导致资源浪费,因为可能创建的实例对象并没有被使用到。示例如下:

public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() {
        return instance;
    }
}

懒汉式

懒汉式是指在单例对象被使用时才去实例化它,也称为延迟加载。这种实现方式在多线程环境下可能会出现线程安全问题,因为多个线程可能同时判断该对象为null,并同时创建多个实例对象。为了解决这个问题,可以使用双重检查锁定来保证线程安全。示例如下:

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

在上面的代码中,使用了volatile关键字来保证instance变量的可见性和禁止指令重排。

单例模式的应用

单例模式在实际开发中有很多应用场景,例如:

  • 日志模块:保证多个线程写日志时只有一个线程在写;
  • 数据库连接池:保证多个线程共享同一个数据库连接池;
  • 缓存:保证多个线程共享同一个缓存对象。

单例模式的优缺点

单例模式的优点:

  • 单例模式可以保证一个类只有一个实例对象,节省系统资源;
  • 单例模式提供了一个全局访问点,方便其他代码获取该实例对象。

单例模式的缺点:

  • 单例模式容易造成内存泄漏;
  • 单例模式对OOP特性支持不友好,例如继承、多态等。

示例说明

以下是一个经典的双重检查锁定实现的单例模式示例:

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

另外,Java中的Runtime类使用了单例模式,保证只有一个Runtime实例对象。例如,以下代码获取Runtime实例对象:

Runtime runtime = Runtime.getRuntime();

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解Java设计模式之单例模式 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • Eclipse右键菜单中的新建菜单怎么设置初始化选项?

    要设置Eclipse右键菜单中新建菜单的初始化选项,需要进行以下步骤: 打开Eclipse,在工作区内选择您要设置的项目文件夹,右击鼠标选中“New”菜单,然后选择“Other”菜单项。 在弹出的 “New” 对话框中选择您需要自定义初始化选项的文件类型,然后点击“Next”按钮。 在下一个对话框中,您可以看到一些选项如“File Name”、“Packag…

    other 2023年6月20日
    00
  • Go项目的目录结构详解

    Go项目的目录结构详解 在Go语言中,一个项目的目录结构对于代码的组织和维护非常重要。一个良好的目录结构可以提高代码的可读性和可维护性。下面是一个常见的Go项目的目录结构示例: myproject/ ├── cmd/ │ └── myapp/ │ └── main.go ├── pkg/ │ └── mypackage/ │ └── mypackage.go…

    other 2023年9月7日
    00
  • htmlvideomuted属性

    以下是“htmlvideomuted属性”的完整攻略: HTML Video muted属性 HTML Video元素是用于在网页中嵌入视频的标准元素。muted属性是Video元素的一个布尔属性,用于控制视频是否静音播放。本攻略中,我们将详细讲解HTML Video muted属性的使用方法。 使用方法 要使用HTML Video muted属性,我们需要…

    other 2023年5月8日
    00
  • Mybatis延迟加载和缓存深入讲解

    Mybatis 是一个 Java 持久层框架,它提供了灵活、高效的数据访问支持,其中数据查询功能更是 Mybatis 的一大特点。在我的博客中,我对 Mybatis 的两个重要特性进行了详细的解释,即延迟加载和缓存。 Mybatis 延迟加载 Mybatis 延迟加载是指,当查询数据时,不会立即将关联对象加载到内存中,而是采用按需获取的方式,当访问关联对象时…

    other 2023年6月25日
    00
  • Spring Bean生命周期源码原理图解

    标准化的Markdown文本通常会包含以下内容: 标题 子标题 次级子标题 正文内容 列表项1 列表项2 列表项3 数字列表项1 数字列表项2 数字列表项3 代码块如下: 这里是代码块 int a = 1; String str = "hello"; System.out.println(str); 以下是“Spring Bean生命周期…

    other 2023年6月27日
    00
  • 深入了解以“.”结尾的文件夹

    深入了解以“.”结尾的文件夹 在Linux中,文件夹名字以“.”结尾代表这个文件夹是一个隐藏文件夹。通常用于存放配置文件或者临时文件等不需要被用户直接访问的文件夹。 但是有时候,我们还是需要了解这些隐藏文件夹的具体内容或者使用它们存储的文件。下面是深入了解以“.”结尾的文件夹的完整攻略。 显示隐藏文件夹 默认情况下,Linux会将以“.”开头的文件或者文件夹…

    other 2023年6月26日
    00
  • vue项目使用axios封装request请求的过程

    以下是基于Vue项目使用Axios封装Request请求的完整攻略。 1. 准备工作 在使用Axios进行Request请求之前,需要先安装Axios插件,命令如下: npm install axios –save 安装完毕后,在Vue的入口文件中(一般是main.js)中引入Axios并配置相关信息: import axios from ‘axios’ …

    other 2023年6月25日
    00
  • juc面试题目

    JUC面试题目攻略 JUC(Java Util Concurrent)是Java中用于并发编程的工具包,包含了许多用于多线程编程的类口。在JUC面试中,常见的问题包括线程池、锁、原子类等。本攻略将详细介绍JUC面试题目的解答方法,并提供两个示例说明。 线程池 问题1:线程池的作用是什么? 答:线程池一种用于管理程的机制,它可以在需要时创建线程,并在不需要时用…

    other 2023年5月7日
    00
合作推广
合作推广
分享本页
返回顶部