Java实现单例模式的五种方法介绍

5种Java实现单例模式的方法介绍

在Java编程中,当我们希望某个类只有一个实例存在时,就需要使用单例模式。下面介绍5种Java实现单例模式的方法:

方法1:饿汉式单例模式

这种方式基于classloder机制避免了多线程的同步问题,不过instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法,但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。

示例:

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

方法2:懒汉式单例模式(线程不安全)

这种方法实现起来很简单,只需要在第一次调用的时候实例化对象即可,但是在多线程下是不安全的。

示例:

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

方法3:懒汉式单例模式(线程安全,效率低)

这种方法考虑到了线程安全,但是效率很低,因为整个方法被synchronized所修饰,因此每次调用getInstance时都要对对象加锁,试图通过减小锁的范围提高效率,结果往往会出现错误或不可靠的情况。

示例:

public class Singleton3 {
    private static Singleton3 instance;
    private Singleton3(){}
    public static synchronized Singleton3 getInstance(){ //加锁
        if(instance == null){
            instance = new Singleton3();
        }
        return instance;
    }
}

方法4:双检锁/双重校验锁(DCL,即double-checked locking)

这种方法致力于解决懒汉式单例模式(线程安全,效率低)的效率问题,只有在第一次创建对象的时候才会加锁,达到了又能解决线程安全问题,又能提高效率的目的。

示例:

public class Singleton4 {
    private volatile static Singleton4 instance;// volatile:禁止指令重排序
    private Singleton4(){}
    public static Singleton4 getInstance(){
        if(instance == null){
            synchronized (Singleton4.class){  //加锁
                if(instance == null){
                    instance = new Singleton4();
                }
            }
        }
        return instance;
    }
}

方法5:静态内部类单例模式

这种方法也是懒汉式单例模式的一种形式,但是相对于其他方法而言更为安全高效。当Singleton5类被载入JVM时,其内部类SingletonHolder并不会被初始化。只有当调用getInstance方法时,才会加载SingletonHolder类,从而实例化Singleton5。同时,由于SingletonHolder是静态的,所以JVM不会重新加载。

示例:

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

以上5种方法各有优缺点,根据不同的情况选择合适的单例模式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java实现单例模式的五种方法介绍 - Python技术站

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

相关文章

  • Java Swing 多线程加载图片(保证顺序一致)

    Java Swing 多线程加载图片是一种在图形界面中快速显示大量图片的思路。在实现过程中,通过多线程并发加载图片,可以提高程序的运行效率,同时通过”保证顺序一致”的要求,可以使得程序在显示图片时始终保持正确的顺序,避免了一些错误和混淆。下面是交互过程及详细攻略。 交互过程 用户打开网站后,滑动页面会有几百张被切割成小图片的性感美女图片实时刷新显示,用户可以…

    Java 2023年5月18日
    00
  • 在 Linux 上安装Apache+ApacheJServ+JSP

    安装Apache和Apache JServ: 首先在终端中运行以下命令更新软件包列表: sudo apt-get update 接着,运行以下命令安装Apache和Apache JServ: sudo apt-get install apache apache-jserv 安装完成后,Apache服务会自动启动。可以在浏览器中输入localhost,来查看A…

    Java 2023年6月15日
    00
  • 通过实例了解JavaBean开发及使用过程解析

    当我们在开发Java应用时,经常需要定义一些Java对象来传递数据。这些对象通常被称为JavaBean。JavaBean是符合特定规范的Java类,它通常具有以下特征: 具有公共的无参数构造函数 存取方法遵循JavaBean的规范 实现可序列化接口 在下面的过程中,我将通过两个实例来说明JavaBean的开发及使用过程: 示例1:开发JavaBean pub…

    Java 2023年6月15日
    00
  • springboot命令行启动的方法详解

    Spring Boot命令行启动的方法详解 Spring Boot是一个简化的框架,使得Spring应用程序的创建和开发变得更加容易。接下来我会详细讲解如何使用Spring Boot命令行启动一个应用程序。 1. 配置环境 在开始之前,需要确保已经安装了JDK和Maven,并且已经配置好了环境变量。可以通过java -version和mvn -version…

    Java 2023年5月26日
    00
  • java基础知识I/O流使用详解

    Java基础知识I/O流使用详解 1. I/O流概述 Java I/O流用于处理与设备(如磁盘、屏幕、键盘等)的输入和输出。在Java中,I/O流分为两个类型:字节流和字符流。字节流用于以字节为单位读取和写入数据,而字符流用于以字符为单位读取和写入数据。 I/O流被划分为四个抽象类:InputStream、OutputStream、Reader和Writer…

    Java 2023年5月24日
    00
  • Java递归调用如何实现数字的逆序输出方式

    实现数字逆序输出的方式有多种,其中一种实现方式是使用递归调用算法。下面,我将详细介绍Java递归调用如何实现数字的逆序输出方式。 实现思路 实现逆序输出数字的方式有不同的思路,其中一种是通过递归实现。这种实现思路的基本过程如下: 将输入数字的个位取出,输出; 将剩余数字递归调用方法,重复上述步骤。 代码实现 基于上述实现思路,Java递归调用如何实现数字的逆…

    Java 2023年5月26日
    00
  • Java正则表达式基础入门知识

    来跟你聊一聊Java正则表达式基础入门知识的攻略吧! 什么是正则表达式 正则表达式(Regex,Regular Expression),是用来描述一组字符串匹配模式的规则。 Java支持正则表达式的API是java.util.regex包。正则表达式由字符和运算符构成,用于搜索、替换和提取字符串。 常用正则表达式符号 在开始介绍正则表达式的基础知识之前,让我…

    Java 2023年5月23日
    00
  • 浅谈序列化之protobuf与avro对比(Java)

    下面是浅谈序列化之protobuf与avro对比(Java)完整攻略: Introduction 在Java中,序列化是将对象转换为字节流方便存储和传输的过程。protobuf和avro是两种常用的序列化工具,它们都在大小、速度和兼容性等方面提供了很好的解决方案。在这篇文章中,我们将对它们进行简单的比较和对比,希望能够帮助读者选择适合自己项目的序列化工具。 …

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