Java单例模式的深入了解

Java单例模式的深入了解

单例模式是一种常用的设计模式,它确保一个类只有一个实例,同时提供一种全局访问的方式。

在Java中,单例模式有多种实现方式,我们既可以使用经典的饿汉式实现,也可以使用懒汉式、静态内部类等方式实现。本篇攻略将为大家深入讲解Java单例模式的各种实现方式及其优缺点,同时提供一些示例说明。

一、饿汉式单例模式

饿汉式单例模式是最简单的一种实现方式,它的核心思想是在类加载时创建实例对象,以确保全局只有一个实例。

饿汉式单例模式的实现方式如下:

public class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}

在以上代码中,我们将实例对象instance定义成static final类型,确保了全局只有一个实例。同时,构造函数被声明为private,避免了外部直接创建实例。

饿汉式单例模式的优点:

  • 实现简单,代码量少。
  • 线程安全,可以保证全局只有一个实例。

饿汉式单例模式的缺点:

  • 实例对象在类加载时被创建,如果该实例从未被使用,就会造成内存浪费。

二、懒汉式单例模式

懒汉式单例模式是另一种常用的实现方式,它的核心思想是在第一次使用时创建实例对象,以减少内存浪费。

懒汉式单例模式的实现方式如下:

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

在以上代码中,我们将实例对象instance初始化为null,只有在第一次调用getInstance()方法时才会创建实例对象。同时,getInstance()方法被声明为synchronized类型,确保线程安全。

懒汉式单例模式的优点:

  • 只有在需要时才会创建实例,可以避免内存浪费。
  • 线程安全,可以保证全局只有一个实例。

懒汉式单例模式的缺点:

  • 每次调用getInstance()方法都需要进行线程同步,可能会影响性能。
  • 由于是在第一次使用时才创建实例,因此如果多线程同时调用getInstance()方法,可能会创建多个实例。

三、静态内部类单例模式

静态内部类单例模式是一种较为优雅的实现方式,它的核心思想是在内部类中创建实例对象,以确保全局只有一个实例。

静态内部类单例模式的实现方式如下:

public class Singleton {
    private Singleton() {}

    private static class SingletonHolder {
        private static final Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}

在以上代码中,我们将实例对象instance放在内部静态类SingletonHolder中,当getInstance()方法被调用时,才会初始化SingletonHolder类,并创建唯一的实例对象。

静态内部类单例模式的优点:

  • 实现简单,线程安全。
  • 只有在需要时才会创建实例,可以避免内存浪费。

静态内部类单例模式的缺点:

  • 需要理解静态内部类的概念,阅读代码的过程中可能需要花费更多时间。

四、示例说明

1. 单线程环境下的示例

在单线程环境下,无论使用哪种实现方式,都可以保证全局只有一个实例:

Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();

assert(singleton1 == singleton2); // true

在以上代码中,我们通过两次调用getInstance()方法获取Singleton实例,然后通过assert()方法验证它们是否相等。

2. 多线程环境下的示例

在多线程环境下,饿汉式单例模式会产生多个实例的问题,懒汉式单例模式和静态内部类单例模式则可以通过加锁的方式保证线程安全:

// 懒汉式单例模式示例
ExecutorService executor = Executors.newFixedThreadPool(2);
List<Singleton> results = new ArrayList<>();
for (int i = 0; i < 100; i++) {
    executor.submit(() -> {
        Singleton singleton = Singleton.getInstance();
        results.add(singleton);
    });
}
executor.shutdown();
while (!executor.isTerminated());
assert(results.size() == 1);

// 静态内部类单例模式示例
ExecutorService executor = Executors.newFixedThreadPool(2);
List<Singleton> results = new ArrayList<>();
for (int i = 0; i < 100; i++) {
    executor.submit(() -> {
        Singleton singleton = Singleton.getInstance();
        results.add(singleton);
    });
}
executor.shutdown();
while (!executor.isTerminated());
Set<Singleton> set = new HashSet<>(results);
assert(results.size() == 1);
assert(set.size() == 1);

在以上代码中,我们通过线程池执行100个线程,每个线程都会调用getInstance()方法获取Singleton实例,并将它们添加到List或Set中。

由于饿汉式单例模式没有考虑多线程的情况,因此results列表可能会包含多个实例。而懒汉式单例模式和静态内部类单例模式使用了加锁的方式,确保了全局只有一个实例。其中,静态内部类单例模式需要验证List和Set中是否只有一个实例,因为存在单例被反序列化后出现多个实例的情况。

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

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

相关文章

  • java如何使用Lombok更优雅地编码

    Java开发中,有很多操作都是重复而无聊的,例如get/set方法的编写。通过使用Lombok,可以在编码时更加优雅,省去这些重复的部分。下面是Java如何使用Lombok更优雅地编码的完整攻略: 1. 安装Lombok 首先在Maven中,添加Lombok的依赖: <dependency> <groupId>org.projectl…

    Java 2023年5月20日
    00
  • java实现二维数组转置的方法示例

    针对”java实现二维数组转置的方法示例”,我为您提供完整攻略如下: 一、题目分析 二维数组转置是将行和列的位置互换,即行变为列,列变为行,其基本原理是通过两层循环,依次交换每一个元素。 二、Java实现方法 Java实现二维数组转置可以按以下步骤进行: 1.定义原始的二维数组: 我们先定义原始的二维数组,一般可以通过随机生成数或者手动初始化等方法来实现。 …

    Java 2023年5月26日
    00
  • 云服务器(Linux)安装部署Kafka的详细过程

    云服务器(Linux)安装部署Kafka的详细过程 作为一种分布式消息系统,Kafka 可以快速处理大规模的实时数据。在云服务器中进行 Kafka 的部署和安装,可以更加方便地管理和维护 Kafka 的使用。 1. 安装 Java 环境 由于 Kafka 是基于 Java 编写的,因此在开始安装 Kafka 之前,需要先安装 Java 环境(JDK 8 或以…

    Java 2023年5月20日
    00
  • JAVA velocity模板引擎使用实例

    下面是关于“JAVA velocity模板引擎使用实例”的详细讲解。 什么是Velocity模板引擎 Velocity模板引擎是一种基于文本模板的渲染引擎,支持将变量、逻辑处理、循环等结构和语法写在模板里面,然后使用程序将模板中的变量值替换成真正的值后输出。Velocity模板引擎是一种轻量级的模板引擎,具有易读易懂、易扩展等特点,被广泛应用于各种JAVA …

    Java 2023年5月19日
    00
  • 最详细的文件上传下载实例详解(推荐)

    首先,我们需要明确一下本文的目的,它是为了向初学者介绍文件上传和下载的基本概念和实现方式,帮助他们更好地掌握这些技能。本文将结合两个示例,详细讲述文件上传和下载的实现过程。 文件上传 1. 准备工作 在进行文件上传之前,我们需要在后端准备好对应的接口,接口负责接收前端传过来的文件并保存至后端服务器中。 2. 前端实现 在前端页面,我们需要使用<inpu…

    Java 2023年5月19日
    00
  • 用Java生成二维码并附带文字信息

    生成二维码并附带文字信息可以通过Java中的ZXing库来实现。下面是具体的步骤: 1. 引入ZXing库 首先需要引入ZXing库,在Maven项目中可以通过添加以下依赖来引入: <dependency> <groupId>com.google.zxing</groupId> <artifactId>core…

    Java 2023年5月20日
    00
  • SpringBoot自定义注解API数据加密和签名校验

    首先我想说明一下本次攻略的目的和背景。随着网络技术的快速发展,很多 web 应用都包含了用户敏感信息,数据的安全性也变得越来越重要。而其中一个解决方案就是加密和签名校验。SpringBoot 作为一个主流的开发框架,提供了各种扩展点,开发人员可以通过自定义注解来实现各种功能,其中就包括 API 数据加密和签名校验。我们的攻略就是基于 SpringBoot 自…

    Java 2023年5月20日
    00
  • MySql实现翻页查询功能

    MySql实现翻页查询功能的完整攻略 什么是翻页查询? 翻页查询是指当查询结果集的数据过多,一次显示不全,把数据分页查询以实现多页查询的技巧。这在Web应用程序中非常常用,比如搜索引擎的结果页面,商品列表页等。 实现翻页查询的方式 在MySql中,实现翻页查询可以通过limit关键字实现。limit语句限制查询结果集的行数,并且提供偏移量,以实现分页查询。 …

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