写在前面

🔥我把后端Java面试题做了一个汇总,有兴趣大家可以看看!这里👉

⭐️在反复复习面试题时,我发现不同资料的解释五花八门,容易造成概念混淆。尤其是很多总结性的文章和视频,要么冗长难记,要么过于简略,导致关键知识点含糊不清。

⭐️为了系统梳理知识,我决定撰写一份面试指南,不只是简单汇总,而是融入个人理解,层层拆解复杂概念,构建完整的知识体系。我希望它不仅帮助自己更自信地应对面试,也能为同行提供清晰、实用的参考。


设计模式相关面试题

面试官:单例设计模式

单例设计模式是一种创建型设计模式,核心思想是保证一个类在整个应用中只有一个实例,并提供一个全局的访问入口。它常用于管理共享资源,比如配置、缓存或数据库连接等场景。接下来,我将详细介绍单例模式的实现过程,以常用的懒汉式加双重检查锁定为例说明其设计原理:

首先,为了避免外部直接创建对象,我们将该类的构造方法设为私有。这一步确保了实例只能在类内部被创建,从而杜绝了通过 new 关键字产生多个实例的可能性。

其次,在类内部定义一个私有的静态变量,该变量用于存储单例实例。初始状态下,它的值为 null,这意味着实例尚未被创建。

然后,我们提供一个公共的静态方法来获取该实例。该方法首先判断静态变量是否为 null,如果不为 null,则说明实例已存在,直接返回即可;如果为 null,则进入同步代码块。在同步块内,再次检查实例是否为 null,若仍为 null,则创建该实例。通过双重检查锁定的方式,我们既保证了多线程环境下的线程安全,又避免了每次访问实例时都进行同步操作带来的性能开销。

最后,当实例创建完成后,后续调用获取实例的方法时,都会直接返回该唯一的实例。这样不仅保证了全局唯一性,也提高了系统性能,因为同步操作只在第一次创建实例时执行。

(1)饿汉式(静态常量)
public class Singleton {private static final Singleton INSTANCE = new Singleton();private Singleton() {}public static Singleton getInstance() {return INSTANCE;}
}

特点:类加载时立即初始化,线程安全。

优点:实现简单,无并发问题。

缺点:即使未使用也会占用资源,可能造成浪费。

(2)懒汉式(线程安全)
public class Singleton {private static Singleton instance;private Singleton() {}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

特点:首次调用时初始化,通过synchronized保证线程安全。

缺点:每次调用getInstance()都会同步,性能较低。

(3)双重检查锁(Double-Check Locking)
public class Singleton {private static volatile Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

关键点:通过两次判空减少同步开销,volatile防止指令重排。

适用场景:高并发环境下的延迟初始化。

1. 为什么使用 private 修饰构造器?

  • 目的:防止外部直接创建对象。
  • 原因:单例模式要求整个程序中只能有一个实例,使用 private 修饰构造器可以确保对象只能在类内部创建。

2. 为什么 getInstance() 方法要写成 static 的?不写成 static 的会怎样?

  • 原因
    • getInstance() 方法负责提供唯一的实例,而类的静态方法可以在没有对象实例的情况下直接调用。
    • 如果不写成 static,调用 getInstance() 就需要先创建对象实例,这违背了单例模式的初衷。
  • 不写成 static 的后果
    • 需要实例化对象后才能调用该方法,而单例模式要求在首次调用时创建实例。
    • 无法确保对象是唯一的。
(4)静态内部类
public class Singleton {private Singleton() {}private static class Holder {static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return Holder.INSTANCE;}
}

优势:利用类加载机制保证线程安全,同时实现延迟初始化。

推荐场景:兼顾性能与安全性的通用方案。

(5)枚举单例
public enum Singleton {INSTANCE;// 添加业务方法
}

特点:天然线程安全,支持序列化,防止反射攻击。

最佳实践:Effective Java推荐的实现方式。


面试官:工厂设计模式

工厂设计模式是一种创建型设计模式,它主要用于封装对象的创建过程,从而使客户端不需要直接实例化具体的类,而是通过工厂来获取对象。这种模式提高了代码的灵活性和扩展性。接下来我会详细讲述工厂设计模式的实现过程。

当我们需要创建一个产品对象时,

首先,我们会定义一个抽象的产品接口或者抽象类,明确规定产品的公共行为和属性。这样,无论后续添加多少具体产品,客户端都可以通过同一接口来操作它们。

其次,我们实现具体的产品类,这些类分别实现了抽象产品接口,包含各自独特的业务逻辑和功能。

接着,我们定义一个工厂接口或者抽象工厂类,声明一个创建产品对象的方法。该方法的职责是隐藏具体产品对象的实例化过程,客户端只需要调用这个方法即可获得产品实例。

然后,我们实现具体的工厂类,它们根据传入的参数或内部逻辑,决定创建哪一种具体的产品对象。这样,具体产品的创建细节完全被封装在工厂内部,客户端无需关心对象的创建过程。

最后,当客户端需要一个产品时,它只需调用工厂提供的创建方法,获得对应的产品对象,并直接使用。这种方式不仅降低了客户端与具体产品实现之间的耦合,也方便了系统的扩展和维护。

(1)简单工厂模式(Simple Factory)

简单工厂模式并不是一种正式的设计模式,但它是最基础的形式。它通过一个工厂类根据传入的参数决定创建哪种具体产品。

public class SimpleFactory {public static Product createProduct(String type) {if ("A".equals(type)) {return new ConcreteProductA();} else if ("B".equals(type)) {return new ConcreteProductB();}throw new IllegalArgumentException("Unknown type");}
}// 抽象产品
public interface Product {void use();
}// 具体产品A
public class ConcreteProductA implements Product {@Overridepublic void use() {System.out.println("Using Product A");}
}// 具体产品B
public class ConcreteProductB implements Product {@Overridepublic void use() {System.out.println("Using Product B");}
}

特点:集中管理对象创建逻辑,易于理解和实现。

缺点:违反开闭原则,新增产品时需修改工厂类。

(2)工厂方法模式(Factory Method)

工厂方法模式通过定义一个创建对象的接口,让子类决定实例化哪个类。它将对象的创建延迟到子类中完成。

// 抽象工厂
public abstract class Factory {public abstract Product createProduct();
}// 具体工厂A
public class ConcreteFactoryA extends Factory {@Overridepublic Product createProduct() {return new ConcreteProductA();}
}// 具体工厂B
public class ConcreteFactoryB extends Factory {@Overridepublic Product createProduct() {return new ConcreteProductB();}
}// 抽象产品
public interface Product {void use();
}// 具体产品A
public class ConcreteProductA implements Product {@Overridepublic void use() {System.out.println("Using Product A");}
}// 具体产品B
public class ConcreteProductB implements Product {@Overridepublic void use() {System.out.println("Using Product B");}
}

特点:符合开闭原则,新增产品只需添加新的工厂和产品类。

缺点:每新增一个产品都需要增加对应的工厂类。

(3)抽象工厂模式(Abstract Factory)

抽象工厂模式提供了一组相关或依赖对象的创建接口,而无需指定它们的具体类。适用于需要创建一系列产品的场景。

// 抽象工厂
public interface AbstractFactory {ProductA createProductA();ProductB createProductB();
}// 具体工厂1
public class ConcreteFactory1 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA1();}@Overridepublic ProductB createProductB() {return new ConcreteProductB1();}
}// 具体工厂2
public class ConcreteFactory2 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA2();}@Overridepublic ProductB createProductB() {return new ConcreteProductB2();}
}// 抽象产品A
public interface ProductA {void use();
}// 具体产品A1
public class ConcreteProductA1 implements ProductA {@Overridepublic void use() {System.out.println("Using Product A1");}
}// 抽象产品B
public interface ProductB {void use();
}// 具体产品B1
public class ConcreteProductB1 implements ProductB {@Overridepublic void use() {System.out.println("Using Product B1");}
}

特点:支持创建一组相关的产品,适合复杂系统。

缺点:增加了系统的复杂性,可能需要大量的工厂和产品类。


面试官:生产者消费者设计模式

生产者消费者设计模式是一种用于多线程环境下协调数据生产与消费的并发设计模式,通过引入一个共享缓冲区(如阻塞队列)实现生产者与消费者之间的解耦,从而提升系统的整体性能和资源利用率。接下来,我会讲述其生产与消费的详细过程。

当生产者生成数据时,

首先,生产者根据业务逻辑产生数据,并调用缓冲区提供的接口将数据放入队列中;如果缓冲区已满,生产者会被阻塞,等待空闲空间出现。

其次,消费者不断地从缓冲区中获取数据进行处理;当缓冲区为空时,消费者同样会进入等待状态,直至有新数据被生产者放入。

然后,通过内部的同步机制(如锁、信号量或者直接使用阻塞队列),确保在并发环境下生产者和消费者对共享数据的访问是安全的,不会出现数据竞争或丢失。

最后,随着数据不断地被生产和消费,整个系统实现了生产与消费的有效解耦,不仅提升了并发处理能力,还能灵活应对生产速度和消费速度不匹配的情况,从而保证系统在高并发场景下稳定运行。

(1)基于 BlockingQueue 的实现

Java 提供了线程安全的阻塞队列(如 LinkedBlockingQueue),可以简化生产者-消费者的实现。

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;public class ProducerConsumerWithBlockingQueue {private static final int MAX_SIZE = 5;private final BlockingQueue<Integer> buffer = new LinkedBlockingQueue<>(MAX_SIZE);public void produce() throws InterruptedException {int value = 0;while (true) {buffer.put(value); // 如果缓冲区满,自动阻塞System.out.println("Produced: " + value);value++;Thread.sleep(1000); // 模拟生产耗时}}public void consume() throws InterruptedException {while (true) {int value = buffer.take(); // 如果缓冲区空,自动阻塞System.out.println("Consumed: " + value);Thread.sleep(1500); // 模拟消费耗时}}public static void main(String[] args) {ProducerConsumerWithBlockingQueue pc = new ProducerConsumerWithBlockingQueue();Thread producerThread = new Thread(() -> {try {pc.produce();} catch (InterruptedException e) {Thread.currentThread().interrupt();}});Thread consumerThread = new Thread(() -> {try {pc.consume();} catch (InterruptedException e) {Thread.currentThread().interrupt();}});producerThread.start();consumerThread.start();}
}

特点:BlockingQueue 内部实现了同步机制,代码更简洁。

优点:减少了手动管理锁和条件变量的复杂性,性能更高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97196.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97196.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/97196.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

访问者设计模式

访问者设计模式是一种行为模式&#xff0c;允许您向现有对象结构添加新作&#xff0c;而无需修改其类。 它通过允许您将算法与其作的对象分开来实现这一点。 它在以下情况下特别有用&#xff1a; 您有一个复杂的对象结构&#xff08;如 AST、文档或 UI 元素&#xff09;&#x…

Linux_用 `ps` 按进程名过滤线程,以及用 `pkill` 按进程名安全杀进程

用 ps 按进程名过滤线程&#xff0c;以及用 pkill 按进程名安全杀进程摘要&#xff1a; 过滤线程信息&#xff1a;教你用 ps -C、pgrepps 等多种姿势&#xff0c;既精准又避免误杀。按名字杀进程&#xff1a;用 pkill 一把梭&#xff0c;优雅还是强杀随你选&#xff0c;附带“先…

关于国产 RAC 和分布式研讨

本次研讨核心目标是围绕崖山 DB、达梦 DB、GBASE三款国产数据库&#xff0c;以及数据库内核开发吕工程师的分享&#xff0c;深入了解共享集群 RAC 的开发技术。但实际效果未达预期&#xff0c;参会者多围绕 “共享集群与分布式应用场景” 泛泛而谈&#xff0c;缺乏深度技术拆解…

传输层协议介绍

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档文章目录前言一、TCP协议介绍二、TCP报文格式三、TCP三次握手四、TCP四次挥手五、UDP协议介绍六、常见协议及其端口七、TCP与UDP的不同总结前言提示&#xff1a;这里可以添加本…

Vibe Coding 概念提出者 AndrejKarpathy 谈强化学习。

在预训练时代&#xff0c;关键在于互联网文本。你最需要的是一大批量、多样化且高质量的互联网文档&#xff0c;供模型从中学习。在监督微调&#xff08;SFT&#xff09;时代&#xff0c;核心则是对话数据。人们雇佣合同工人为问题撰写答案&#xff0c;类似于你在 Stack Overfl…

OSI模型和TCP/IP模型区别是什么

问题OSI模型和TCP/IP模型区别是什么我的回答OSI和TCP/IP这两个协议栈有几个主要区别&#xff1a;首先&#xff0c;层次结构不同。OSI是七层模型&#xff1a;物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。而TCP/IP是四层模型&#xff1a;数据链路层、网络层、传…

ros2与gazebo harmonic机械臂仿真项目Moveit2YoloObb的优化

文章目录 关于项目RVIZ控制Gazebo Harmonic仿真机械臂GraphExecuter创建流程并通过Yolo算法抓取螺栓 关于项目 本文介绍ros2与gazebo harmonic机械臂仿真项目Moveit2YoloObb优化的内容&#xff0c;具体的代码细节就不赘述了&#xff0c;主要还是演示效果&#xff0c;包括RVIZ控…

Linux 系统调优与CPU-IO-网络内核参数调优

1. Linux系统调优1.1 安装工具包在开始监控前&#xff0c;需要确保系统已安装以下工具包&#xff0c;它们是后续操作的基础&#xff1a;sysstat&#xff1a;包含 mpstat、iostat、sar 等核心统计工具iotop&#xff1a;专门监控磁盘 I/O 的进程级工具nethogs&#xff1a;按进程查…

laravel学习并连接mysql数据库,给本地vue项目提供接口

下载laravel laravel下载地址phpstudy_pro\WWW\laravel.env文件 DB_CONNECTIONmysql DB_HOST127.0.0.1 DB_PORT3306 DB_DATABASEclgl //你的数据库名称 DB_USERNAMEroot //你的账号 DB_PASSWORDroot //你的密码安装 Laravel CORS 包 composer require fruitcake/laravel-c…

Mybatis 与 Springboot 集成过程详解

Mybatis 与 Springboot 集成过程详解一. 核心概念与优势二.Mybatis 核心类简介1.MybatisAutoConfiguration2.MapperScans3.MapperScannerRegistrar4.MapperFactoryBean5.Configuration6.MapperRegistry7.MapperProxy 与 MapperProxyFactory7.1核心定位与职责7.22. ​​MapperPr…

prometheus alertmanager 对接飞书

alertmanager 直接配置 飞书 的 webhook &#xff0c;发现并不满足飞书接口的 json 格式。报错如下levelerror ts2025-08-28T04:57:02.734Z callerdispatch.go:310 componentdispatcher msg"Notify for alerts failed" num_alerts23 err"prometheusalert-webhoo…

『专利好药用力心脑血管健康』——爱上古中医(28)(健康生活是coder抒写优质代码的前提条件——《黄帝内经》伴读学习纪要)

心脏血管三通康&#xff0c;古时丸药精益装。 笔记模板由python脚本于2025-08-26 18:25:03创建&#xff0c;本篇笔记适合喜欢日常保健养生知识的coder翻阅。 学习的细节是欢悦的历程 博客的核心价值&#xff1a;在于输出思考与经验&#xff0c;而不仅仅是知识的简单复述。 Pyth…

在 .NET 8.0 中实现 JWT 刷新令牌

介绍在 Web 开发领域&#xff0c;安全是重中之重。JSON Web Tokens (JWT) 已成为在各方之间安全传输信息的热门选择。然而&#xff0c;在 JWT 过期后&#xff0c;如何维护用户会话并避免频繁登录至关重要。这正是 JWT 刷新令牌应运而生的地方。在本文中&#xff0c;我们将指导您…

深入解析 git push 命令

1. 基础语法 git push 的基本语法如下: git push <远程仓库名> <本地分支名>:<远程分支名> [选项]<远程仓库名>: 通常是 origin(默认的远程仓库名称)。 <本地分支名>:<远程分支名>: 指定要推送的本地分支以及目标远程分支。如果省略远…

UI弹出动画

简介的UI弹出动画 使用方式很简单 挂载到需要弹出的目标 即可 using UnityEngine; using DG.Tweening; using Unity.VisualScripting;/// <summary>/// 简洁的UI动画脚本/// 直接挂载到UI组件上&#xff0c;调用Play()播放缩放弹出动画/// </summary>public class …

PostgreSQL诊断系列(6/6):配置项全景解析——打造你的专属优化清单

&#x1f517; 作为《PostgreSQL诊断系列》的收官之作&#xff0c;今天我们系统梳理 postgresql.conf 中的核心参数&#xff0c;将前5篇的“诊断”转化为“调优”&#xff0c;打造一套生产环境专属的配置模板。 你是否&#xff1a; 不知道哪些参数该调&#xff1f;害怕调错导致…

Flink Slot 不足导致任务Pending修复方案

当前有3个虚拟机节点&#xff0c;每个节点配置的slot节点数量是4&#xff0c;${FLINK_HOME}/conf/flink-conf.yaml 关于slot的配置如下&#xff1a; # The number of task slots that each TaskManager offers. Each slot runs one parallel pipeline. taskmanager.numberOfTas…

亚马逊合规风控升级:详情页排查与多账号运营安全构建

2025年亚马逊掀起的大规模扫号行动&#xff0c;聚焦商品详情页合规性审查&#xff0c;标志着跨境电商合规监管进入严风控时代&#xff0c;此次行动以关键词规范与定价诚信为核心&#xff0c;大量卖家因内容违规遭遇账号停用&#xff0c;对于卖家而言&#xff0c;构建系统化的合…

FISCO-BCOS-Python 模板

基于Python-SDK的FISCO BCOS区块链HelloWorld模板&#xff0c;提供了简单的问候语设置和查询功能。本项目采用现代Python开发实践&#xff0c;包含完整的配置管理、测试框架和项目结构。 快速开始 仓库地址&#xff1a;git clone https://gitee.com/atanycosts/python-fisco-te…

移动端(微信等)使用 vConsole调试console

本文介绍了一种在移动端真机上进行调试的方法——使用VConsole。通过简单的安装步骤和代码配置&#xff0c;开发者可以在移动端直接查看console.log输出&#xff0c;极大提升了调试效率。 摘要生成于 C知道 &#xff0c;由 DeepSeek-R1 满血版支持&#xff0c; 前往体验 >作…