教你java面试时如何聊单例模式

当被问到单例模式的时候,需要掌握以下几点:

1.单例模式定义及应用场景

单例模式是一种创建型设计模式,用于确保某个类只有一个实例,且该实例提供了全局访问点。该模式常用于线程池、日志、缓存、配置文件等需要只有一个实例的对象。

2.单例模式的实现方法

  • 饿汉式

在类加载的时候就将单例对象创建好,因此不存在线程安全问题,但是会浪费一定的内存空间。

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

在需要使用单例对象时才创建,在多线程情况下可能会存在线程不安全问题,例如线程 A 和线程 B 同时尝试获取单例对象,A 获取到锁初始化单例之后,B 可能会再次进入 if 语句中,从而创建出新的实例。

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 volatile Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance(){
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

3.单例模式的线程安全性问题

  • 线程不安全

在多线程场景下,单例模式的实现可能会存在线程安全问题。

public class Singleton {
    private static Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance(){
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}
  • 线程安全

使用volatile和synchronized等关键字可以保证单例模式的线程安全。

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

示例说明

示例1:懒汉式线程不安全示例

public class SingletonDemo {
    public static void main(String[] args) {
        Runnable runnable = () -> {
            Singleton singleton = Singleton.getInstance();
            System.out.println(singleton.hashCode());
        };
        Thread thread1 = new Thread(runnable, "Thread-1");
        Thread thread2 = new Thread(runnable, "Thread-2");
        thread1.start();
        thread2.start();
    }
}

示例输出:

217227986
1842773630

示例2:双重校验锁线程安全示例

public class SingletonDemo {
    public static void main(String[] args) {
        Runnable runnable = () -> {
            Singleton singleton = Singleton.getInstance();
            System.out.println(singleton.hashCode());
        };
        Thread thread1 = new Thread(runnable, "Thread-1");
        Thread thread2 = new Thread(runnable, "Thread-2");
        thread1.start();
        thread2.start();
    }
}

示例输出:

168044823
168044823

以上两个示例展示了懒汉式和双重校验锁两种单例模式的实现方式及其线程安全性问题。同时还介绍了单例模式的定义及应用场景。在面试中,可以根据面试官的问题来展开讨论,并举一些实际项目中的应用场景来巩固知识。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:教你java面试时如何聊单例模式 - Python技术站

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

相关文章

  • js将键值对字符串转为json字符串的方法

    将键值对字符串转为JSON字符串的方法,可以使用JSON.parse()函数来实现。下面给出详细的攻略。 1. 确认键值对字符串的格式 在转换之前,需要确保键值对字符串的格式正确。格式应该是键值对之间使用逗号分隔,键与值之间使用冒号分隔,整个字符串包裹在一对花括号内。 例如,以下的字符串是合法的键值对字符串: {"name": &quot…

    Java 2023年5月26日
    00
  • Java编程实现获取当前代码行行号的方法示例

    在讲解“Java编程实现获取当前代码行行号的方法示例”的完整攻略之前,我们先来了解一下所涉及的相关概念: 首先,所谓的行号(line number),就是指代码中每一行所对应的编号。在Java代码中,每个代码文件都有其独立的行号,而且每行都是有编号的。 其次,获取行号有两种常用的方法: 1.使用StackTraceElement类中的getLineNumbe…

    Java 2023年5月26日
    00
  • TOMCAT+IIS配置方法

    下面是 “TOMCAT+IIS配置方法” 的完整攻略: 前置条件 安装好 TOMCAT 及 IIS,并且都能正常启动。 配置步骤 步骤一:修改 IIS 默认端口 为了确保 IIS 和 TOMCAT 能够同时运行,我们需要将 IIS 默认端口从 80 改为其他端口(如:8080)。 打开 IIS 管理器。 点击左边菜单栏的“默认网站”,然后在右边窗口中找到“基…

    Java 2023年5月19日
    00
  • 详解Spring如何整合Mybatis

    下面我会详细讲解如何整合Spring和MyBatis的攻略,包括必要的配置和示例。 一、添加依赖 首先需要在pom.xml中添加以下依赖: <!– Spring –> <dependency> <groupId>org.springframework</groupId> <artifactId>…

    Java 2023年5月19日
    00
  • MyBatis-Plus拦截器对敏感数据实现加密

    大家好,我是网站的作者,本次将为大家讲解如何对敏感数据实现加密,使用的工具是MyBatis-Plus拦截器。下文将分为以下几个部分: MyBatis-Plus拦截器简介 敏感数据加密的必要性 敏感数据加密的具体实现 示例说明 MyBatis-Plus拦截器简介 MyBatis-Plus是MyBatis的增强工具包,提供了丰富的功能,包括但不限于自动生成代码、…

    Java 2023年5月26日
    00
  • Java的jstack命令使用示例详解

    Java的jstack命令使用示例详解 一、jstack命令简介 jstack是JDK自带的命令行工具,可以用于查看Java应用程序的线程堆栈信息。它可以显示Java应用程序内所有线程的堆栈信息,包括线程ID、线程名称、线程状态、等待对象、栈帧、堆栈深度等信息。通过jstack命令获取线程堆栈信息,可以帮助检查Java应用程序的线程卡死、死锁等问题。 二、j…

    Java 2023年5月26日
    00
  • java如何实现字符串中的字母排序

    要实现字符串中字母的排序,我们可以使用Java中的字符数组和字符串操作。 步骤如下: 首先,从输入的字符串中创建一个字符数组。 然后,使用Java中提供的排序算法,对字符数组进行排序。 重新构建一个字符串,该字符串是排好序的字符数组的字符串表示形式。 以下是一个示例程序,它演示了如何在Java中实现对字符串中字母的排序: 示例1:使用冒泡排序对字符数组进行排…

    Java 2023年5月26日
    00
  • 在已经使用mybatis的项目里引入mybatis-plus,结果不能共存的解决

    在已经使用MyBatis框架的项目中引入MyBatis-Plus,同样需要引入相应的依赖。同时,需要注意,MyBatis-Plus已经包含了MyBatis的所有功能,如果使用了重复的依赖,会导致冲突的问题。下面是一些解决方案的详细步骤。 1. 排除MyBatis依赖 在使用MyBatis-Plus时,可以通过在引入MyBatis-Plus的POM文件中,通过…

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