java单例五种实现模式解析

Java单例五种实现模式解析

什么是单例模式?

单例模式是指一个类只能被实例化一次,并且全局都可以访问到这个实例。在实际开发中,很多情况下我们只需要一个实例,例如全局配置信息、日志管理等等,这时候使用单例模式可以节省系统资源,减少不必要的开销。

单例模式的特点

  • 保证一个类只有一个实例。
  • 提供一个访问该实例的全局入口。
  • 不能被其他对象实例化。

五种实现模式

1. 饿汉式

线程安全

饿汉式在类被加载的同时就创建好了唯一的实例,故天然的线程安全。

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

示例说明

public static void main(String[] args) {
    Singleton instance1 = Singleton.getInstance();
    Singleton instance2 = Singleton.getInstance();
    System.out.println(instance1 == instance2);
}

输出结果为 true,表明两个实例指向同一内存空间,即单例模式被实现。

2. 懒汉式

线程不安全

懒汉式在第一次使用的时候才创建实例,需要考虑线程安全性问题,否则会出现多个实例的情况。

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

线程安全

使用双重判定锁的方式可以保证线程安全性。

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

示例说明

public static void main(String[] args) {
    Singleton instance1 = Singleton.getInstance();
    Singleton instance2 = Singleton.getInstance();
    System.out.println(instance1 == instance2);
}

输出结果为 true,表明两个实例指向同一内存空间,即单例模式被实现。

3. 静态内部类

这种方式利用了 Classloader 的机制来保证初始化实例时只有一个线程。静态内部类不会在类加载时就初始化,而是当被调用时才进行初始化。

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

示例说明

public static void main(String[] args) {
    Singleton instance1 = Singleton.getInstance();
    Singleton instance2 = Singleton.getInstance();
    System.out.println(instance1 == instance2);
}

输出结果为 true,表明两个实例指向同一内存空间,即单例模式被实现。

4. 枚举类型

枚举类型被限制了元素个数,保证了单例模式的实现,且避免了线程安全问题。

public enum Singleton {
    INSTANCE;
    public void whateverMethod() { }
}

示例说明

public static void main(String[] args) {
    Singleton instance1 = Singleton.INSTANCE;
    Singleton instance2 = Singleton.INSTANCE;
    System.out.println(instance1 == instance2);
}

输出结果为 true,表明两个实例指向同一内存空间,即单例模式被实现。

5. 双重校验锁

这种方式可以在保证线程安全的情况下实现懒加载。

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

示例说明

public static void main(String[] args) {
    Singleton instance1 = Singleton.getInstance();
    Singleton instance2 = Singleton.getInstance();
    System.out.println(instance1 == instance2);
}

输出结果为 true,表明两个实例指向同一内存空间,即单例模式被实现。

总结

以上五种单例实现方式各有优缺点,应根据具体情况选择。选用不合适的单例实现方式会导致系统资源浪费、性能降低及线程安全问题等。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java单例五种实现模式解析 - Python技术站

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

相关文章

  • 玩转SpringBoot中的那些连接池(小结)

    玩转SpringBoot中的那些连接池(小结) 连接池是每个Web应用中必不可少的组件,Spring Boot中默认提供了大量连接池实现,例如HikariCP、Tomcat JDBC、Commons DBCP2等等。本文将介绍这些连接池的优缺点,帮助开发者选择适合自己应用的连接池。 HikariCP HikariCP是Spring Boot中默认的连接池实现…

    Java 2023年5月19日
    00
  • Struts1教程之ActionMapping_动力节点Java学院整理

    Struts1教程之ActionMapping_动力节点Java学院整理 1. 了解ActionMapping ActionMapping 是 Struts1 框架中的一个重要组件,它主要负责将请求的 URL 映射到相应的 Action 类,以便执行对应的业务逻辑。也就是说,我们可以通过 ActionMapping 来实现 URL 到 Action 类及其方…

    Java 2023年5月20日
    00
  • 用js绘图

    下面是关于用JS绘图的完整攻略,步骤如下: 步骤一:准备canvas 在HTML页面中创建一个canvas元素。canvas元素是HTML5中新增的元素,用于绘图。我们可以通过canvas元素的getContext()方法在JavaScript中获取绘图环境,进而进行绘图。这里的绘图环境可以是2D绘图环境或者3D绘图环境。下面是一个示例代码: <can…

    Java 2023年6月15日
    00
  • js获取select标签的值且兼容IE与firefox

    为了获取select标签的值且兼容IE与Firefox,我们可以使用JavaScript编写代码。接下来,我将提供一个完整的攻略来帮助您实现这个目标。 获取select标签的值 我们可以使用JavaScript来获取select标签的值,以下是代码实现的步骤: 首先,使用document.getElementById()方法获取到select标签的引用。 然…

    Java 2023年6月15日
    00
  • JAVA中SSM框架的搭建实现CRUD的方法

    JAVA中SSM框架的搭建实现CRUD操作可以分为以下几个步骤: 1. 搭建环境 首先,我们需要安装必要的软件和工具: JDK Maven Eclipse或IntelliJ IDEA Tomcat MySQL 并配置环境变量和路径。安装完成后,在Eclipse或IntelliJ IDEA中创建一个新的Maven项目。 2. 添加依赖 在pom.xml文件中,…

    Java 2023年6月15日
    00
  • java实现二分法的完整代码

    要实现二分法,需要定义一个函数,函数需要传入三个参数:要查找的数组、要查找的数和数组范围的起点和终点。 下面是标准的Java实现二分法的完整代码示例: public static int binarySearch(int[] nums, int target, int left, int right) { while (left <= right) {…

    Java 2023年5月19日
    00
  • Java SPI机制原理及代码实例

    Java SPI机制原理及代码实例 SPI全称Service Provider Interface。在Java中,SPI是一种以插件化的方式来实现程序的可扩展性的机制,它允许第三方程序向已有的程序添加功能或者替换原有的功能。 SPI的机制原理 SPI机制的基本原理是,一些具有相同接口的服务类,定义了一组标准与规范,由服务提供者实现,以供调用方调用。调用者通过…

    Java 2023年5月19日
    00
  • MyBatis实现动态SQL的实现方法

    关于”MyBatis实现动态SQL的实现方法”,可以从以下三方面进行讲解: MyBatis动态SQL简介 MyBatis动态SQL的实现方法 MyBatis动态SQL的示例 1. MyBatis动态SQL简介 MyBatis是一种基于Java的持久化框架,它可以帮助Java开发者更方便地将Java程序连接到各种关系数据库中。MyBatis动态SQL是MyBa…

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