Java中的单例模式详解(完整篇)

Java中的单例模式是一种常见的设计模式,它用于确保类只有一个实例,并提供全局的访问点。在某些场景下,单例模式可以提高系统的性能和效率。下面是单例模式详解的完整攻略:

什么是单例模式

单例模式(Singleton Pattern)是一种常见的创建型设计模式,它可以确保一个类只有一个实例,并提供全局的访问点。单例模式可以避免不必要的对象创建,提高系统的性能和效率。此外,在一个多线程的环境下,单例模式还可以避免竞态条件和锁竞争。

单例模式的实现

单例模式的实现一般有两种方法:饿汉式和懒汉式。

饿汉式

饿汉式是一种较为简单的单例模式实现方式,它的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了。常见的实现方式如下:

public class Singleton {
    // 在类加载的时候就创建单例对象
    private static Singleton instance = new Singleton();
    // 私有构造函数,确保外部无法实例化该类
    private Singleton() {}
    // 获取单例的唯一访问点
    public static Singleton getInstance() {
        return instance;
    }
}

懒汉式

懒汉式是一种比较懒惰的单例模式实现方式,它的特点是单例的实例只会在第一次调用 getInstance 方法时被创建。常见的实现方式如下:

public class Singleton {
    // 声明单例,但暂时不创建单例对象
    private static Singleton instance = null;
    // 私有构造函数,确保外部无法实例化该类
    private Singleton() {}
    // 获取单例的唯一访问点
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

双重校验锁式

双重校验锁式是一种线程安全的懒汉式单例模式实现方式,它的特点是在需要时才会创建单例。通过双重校验锁,既避免了锁竞争,又避免了每次获取锁的开销。常见的实现方式如下:

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;
    }
}

单例模式的使用

单例模式在实际开发中经常用于工具类、配置类、日志类等场景中。下面通过两个示例来说明单例模式的使用。

配置文件工具类

我们经常会用到配置文件来保存应用程序的配置信息。下面是一个配置文件工具类的示例,它可以读取和写入配置文件,并提供全局的访问点。

public class ConfigUtil {
    // 声明单例,但暂时不创建单例对象
    private static volatile ConfigUtil instance = null;
    // 保存配置信息的 Map
    private Map<String, String> configMap = new HashMap<>();
    // 私有构造函数,确保外部无法实例化该类
    private ConfigUtil() {
        // 初始化配置信息
        loadConfig();
    }
    // 加载配置信息
    private void loadConfig() {
        // 读取配置文件,将配置信息保存到 configMap 中
    }
    // 获取单例的唯一访问点
    public static ConfigUtil getInstance() {
        if (instance == null) {
            synchronized(ConfigUtil.class) {
                if (instance == null) {
                    instance = new ConfigUtil();
                }
            }
        }
        return instance;
    }
    // 获取配置信息
    public String getConfigValue(String key) {
        return configMap.get(key);
    }
    // 设置配置信息
    public void setConfigValue(String key, String value) {
        configMap.put(key, value);
    }
    // 保存配置信息到文件
    public void saveConfig() {
        // 将 configMap 中的配置信息写入配置文件
    }
}

日志记录器

日志记录器通常用于记录应用程序的运行日志。下面是一个简单的日志记录器的示例,它可以记录日志,并提供全局的访问点。

public class Logger {
    // 声明单例,但暂时不创建单例对象
    private static volatile Logger instance = null;
    // 日志文件的路径
    private String logFilePath = "";
    // 私有构造函数,确保外部无法实例化该类
    private Logger() {}
    // 获取单例的唯一访问点
    public static Logger getInstance() {
        if (instance == null) {
            synchronized(Logger.class) {
                if (instance == null) {
                    instance = new Logger();
                }
            }
        }
        return instance;
    }
    // 写入日志
    public void log(String message) {
        // 将日志写入日志文件
    }
    // 设置日志文件的路径
    public void setLogFilePath(String logFilePath) {
        this.logFilePath = logFilePath;
    }
}

单例模式的扩展

单例模式还可以通过一些扩展方式来增加功能或者优化性能,常见的扩展方式如下:

线程池化单例

线程池化单例是一种将多个单例对象缓存到线程池中,从而提高单例对象的重用率和系统的性能。

延迟加载单例

延迟加载单例是一种将单例对象的创建延迟到第一次使用时再进行,从而避免了不必要的对象创建。

总结

单例模式是一种常见的设计模式,它可以确保一个类只有一个实例,并提供全局的访问点,从而提高系统的性能和效率。单例模式的实现一般有饿汉式、懒汉式和双重校验锁式等方式。在实际开发中,单例模式经常用于工具类、配置类、日志类等场景中。单例模式还可以通过线程池化、延迟加载等方式进行扩展。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中的单例模式详解(完整篇) - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • 什么是Java内存溢出?

    Java内存溢出是指在Java程序运行过程中,申请的内存超过了JVM所能提供的上限,导致程序无法正常运行或者直接导致JVM崩溃。这是Java程序中常见的一个问题,需要我们去识别和解决。 为了解决Java内存溢出问题,我们可以采用以下几个步骤: 第一步:确认内存溢出的类型 Java内存溢出一般分为两类:堆栈内存溢出和非堆栈内存溢出。我们需要根据JVM的错误提示…

    Java 2023年5月11日
    00
  • mybatis基本实例详解

    Mybatis基本实例详解 Mybatis是一款开源的持久化框架,它可以将数据库的操作和Java代码解耦,大大简化了数据访问层的开发。本文将介绍Mybatis基本实例,包含如下内容: Mybatis简介 Mybatis基本配置 Mybatis增删改查示例1 Mybatis增删改查示例2 Mybatis简介 Mybatis是一款优秀的持久层框架,它为Java开…

    Java 2023年5月20日
    00
  • Java形参和实参的实例之Integer类型与Int类型用法说明

    这里我会详细讲解Java中的形参和实参的使用,以及Integer类型和int类型之间的区别和用法。 形参和实参 在Java中,定义方法时需要指定参数,即形参。形参是函数或方法中的参数变量,用来接收调用该函数或方法时传递的实参。在调用方法时,我们需要传入具体的参数值,这些值即为实参。 形参和实参之间的传递是值传递(pass by value)的方式,即将实参的…

    Java 2023年5月26日
    00
  • Java实现AES加密算法的简单示例分享

    那么我将详细讲解“Java实现AES加密算法的简单示例分享”的完整攻略,包括实现步骤,示例说明等。 第一步:引入依赖 Java实现AES加密算法需要引入如下两个依赖: <dependency> <groupId>javax.crypto</groupId> <artifactId>javax.crypto-ap…

    Java 2023年5月26日
    00
  • java 数值类型分秒时间格式化的实例代码

    让我来为你详细讲解一下“Java数值类型分秒时间格式化的实例代码”的攻略。 一、需求分析 在进行实例编写前,我们先来分析一下需求: 我们需要实现一个功能能够将时间以及数值类型的分秒转化成如下格式:mm:ss,例如:将80秒转化成01:20,将150秒转化成02:30等。 二、实现思路 基于上面的需求,我们大概可以想到以下的实现思路: 通过对秒数的模运算来计算…

    Java 2023年5月20日
    00
  • Java 切割字符串的几种方式集合

    Java 切割字符串的几种方式集合 在Java中,切割字符串是非常常见的操作。本文将介绍Java中切割字符串的几种方式,包括使用StringTokenizer、split()函数和正则表达式等。 使用StringTokenizer java.util.StringTokenizer类是Java内置用来分割字符串的类,它可以将一个字符串按照指定的分隔符进行分割…

    Java 2023年5月26日
    00
  • Spring Boot四大神器之CLI的具体使用

    Spring Boot CLI是Spring Boot的一个命令行工具,它可以帮助我们快速创建、运行和调试Spring Boot应用程序。在本文中,我们将详细讲解Spring Boot CLI的具体使用,包括如何安装、如何创建和运行Spring Boot应用程序等。 安装 在使用Spring Boot CLI之前,我们需要先安装它。以下是安装Spring B…

    Java 2023年5月15日
    00
  • java实现的日期时间转换工具类完整示例

    下面我将详细讲解“Java实现的日期时间转换工具类完整示例”的完整攻略。 引言 在实际开发中,经常需要进行日期时间的转换和处理,比如将字符串表示的时间转换为Date对象,将Date对象格式化为字符串,计算日期时间差等等。为了方便我们进行这些操作,可以使用Java中的日期时间工具类库。下面,我们将详细介绍如何使用Java实现日期时间转换工具类。 简介 Java…

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