写点什么

十年磨一剑,必出精品——Java 面试常见场景题及参考答案!

  • 2025-06-18
    湖南
  • 本文字数:10757 字

    阅读完需:约 35 分钟

Java 面试常见场景题及参考答案

多线程与并发

场景题:如何实现一个线程安全的单例模式?

publicclassSingleton {privatestaticvolatile Singleton instance;
privateSingleton() {}
publicstatic Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {                    instance = newSingleton();                }            }        }return instance;    }}
复制代码


双重检查锁定(DCL)结合volatile关键字,避免指令重排序和确保可见性。

场景题:HashMap线程不安全的表现是什么?如何解决? 在多线程环境下,HashMap的扩容操作可能导致死循环或数据丢失。解决方案:


  • 使用ConcurrentHashMap


  • 使用Collections.synchronizedMap()


  • 改用Hashtable(性能较低)

JVM 与性能优化

场景题:OOM 如何排查?


  • 使用jmap -heap <pid>查看堆内存分配


  • 通过jstat -gcutil <pid>观察 GC 情况


  • 分析-XX:+HeapDumpOnOutOfMemoryError生成的 dump 文件


  • 常见原因:内存泄漏、堆设置过小、大对象分配

场景题:Young GC 频繁可能是什么原因?


  • Survivor 区空间不足


  • Eden 区设置过小


  • 短生命周期对象过多


  • 存在内存泄漏导致对象过早晋升

Spring 框架

场景题:@Autowired@Resource区别


  • @Autowired按类型注入,需配合@Qualifier指定名称


  • @Resource默认按名称匹配,支持 JSR-250 标准


  • @Autowired属于 Spring 生态,@Resource是 Java 标准注解

场景题:Spring 事务失效的常见场景


  • 方法非 public 修饰


  • 自调用(同一类中方法调用)


  • 异常类型未被捕获(默认只回滚 RuntimeException)


  • 数据库引擎不支持事务(如 MyISAM)

数据库与缓存

场景题:MySQL 死锁如何分析?


  • 查看SHOW ENGINE INNODB STATUS的死锁日志


  • 分析事务隔离级别和加锁顺序


  • 常见解决方案:调整事务大小、统一访问顺序、使用乐观锁

场景题:Redis 缓存穿透解决方案


  • 布隆过滤器拦截无效请求


  • 缓存空对象(设置短 TTL)


  • 接口层增加参数校验


  • 热点数据预加载

系统设计

场景题:如何设计一个分布式 ID 生成器?


  • UUID:简单但无序且存储空间大


  • 数据库自增序列:需要中心化数据库


  • Snowflake 算法:64 位 ID(时间戳+机器 ID+序列号)


  • Redis 原子操作:INCR 或 INCRBY 命令

场景题:秒杀系统设计要点


  • 分层削峰:前端限流+中间层排队+后端异步处理


  • 库存预热:提前缓存库存数据


  • 读写分离:查询走缓存,写入用队列


  • 熔断降级:核心与非核心服务隔离

代码实践

场景题:反转链表实现

public ListNode reverseList(ListNode head) {ListNodeprev=null;ListNodecurr= head;while (curr != null) {ListNodenextTemp= curr.next;        curr.next = prev;        prev = curr;        curr = nextTemp;    }return prev;}
复制代码


场景题:手写生产者消费者模型

publicclassBlockingQueueExample {privatefinal BlockingQueue<Integer> queue = newLinkedBlockingQueue<>(10);
classProducerimplementsRunnable {publicvoidrun() {try {                queue.put(newRandom().nextInt());            } catch (InterruptedException e) {                Thread.currentThread().interrupt();            }        }    }
classConsumerimplementsRunnable {publicvoidrun() {try {                System.out.println(queue.take());            } catch (InterruptedException e) {                Thread.currentThread().interrupt();            }        }    }}
复制代码


注意:实际面试中应结合具体业务场景展开,以上答案为通用性解决方案,需根据面试官追问进行深度延伸。


并发与多线程场景


  1. 场景:如何设计一个线程安全的计数器?


    synchronized 方法/代码块:简单,但性能较差(锁粒度粗)。


    ReentrantLock:更灵活(可中断、公平锁等),性能可能略优于 synchronized(取决于竞争程度)。


    AtomicInteger / AtomicLong最佳选择(针对计数器)。底层使用 CAS (Compare-And-Swap) 操作,无锁,性能极高。incrementAndGet()getAndIncrement() 等方法是原子的。


    LongAdder (Java 8+):在超高并发写多读少的场景下性能优于 AtomicLong。采用分段思想分散竞争。



    核心点: 高并发下的原子性和可见性。


    方案:


    答题要点: 优先推荐 AtomicInteger/AtomicLong,解释 CAS 原理和优势;提到 LongAdder 适用场景;说明 synchronized 和 ReentrantLock 的适用性但非最优。



  2. 场景:设计一个连接池(如数据库连接池)。需要考虑哪些因素?如何实现核心功能(获取连接、释放连接、管理连接数)?


    数据结构: 使用 BlockingQueue (如 LinkedBlockingQueue 或 ArrayBlockingQueue) 存放空闲连接。天然支持并发阻塞操作。


    初始化: 启动时创建一定数量的连接放入队列。


    获取连接 (getConnection()):


    释放连接 (releaseConnection(Connection conn)):


    管理:



    尝试从队列取连接 (poll() 非阻塞或 take() 阻塞)。


    如果队列为空且未达最大连接数,创建新连接。


    如果已达最大连接数,等待 (take()) 或超时失败 (poll(timeout)),或抛出异常。



    检查连接是否有效(可选,或由健康检查处理)。


    如果有效且空闲队列未满,放回队列 (offer() 或 put())。


    如果无效或队列已满,直接关闭连接。



    最大/最小连接数: 配置参数控制。


    超时: 获取连接超时 (poll(timeout)),连接空闲超时(后台线程扫描队列,关闭超时空闲连接)。


    健康检查: 定期或使用前验证连接有效性。


    拒绝策略: 当连接池耗尽且无法创建新连接时如何处理新请求(抛异常、等待、降级)。



    核心点: 资源管理、并发控制、连接复用、超时处理、健康检查。


    方案要素:


    答题要点: 强调使用 BlockingQueue 简化并发控制;说明核心方法的流程;提到关键管理特性(超时、健康检查、大小限制);可以对比开源池(如 HikariCP)的设计理念。



  3. 场景:设计一个生产者-消费者模型。生产者不断生产任务放入队列,消费者从队列取出任务处理。如何保证线程安全和高效率?


    核心组件: BlockingQueue (如 LinkedBlockingQueueArrayBlockingQueue)。


    生产者 (Producer): 调用 queue.put(task) 或 queue.offer(task, timeout) 放入任务。如果队列满,put 会阻塞,offer 可超时或返回 false。


    消费者 (Consumer): 调用 queue.take() 或 queue.poll(timeout) 取出任务处理。take 在队列空时阻塞。


    线程池: 消费者通常使用线程池 (ExecutorService) 管理,方便并发处理和资源控制。


    优雅关闭: 使用 poison pill(特殊标记任务)通知消费者停止,或使用 ExecutorService.shutdown()/shutdownNow()



    核心点: 线程间安全通信、解耦、流量控制。


    方案:


    答题要点: 强调 BlockingQueue 是核心,完美契合此模型;说明生产者和消费者的基本操作;提到线程池管理消费者;简述关闭策略。



  4. 场景:如何实现一个简单的缓存 (Cache)?需要考虑缓存失效、淘汰策略、并发访问。


    数据结构: ConcurrentHashMap (核心存储)。考虑使用 LinkedHashMap (可支持 LRU) 或第三方库 (Guava Cache, Caffeine)。


    基本操作 (get(key)put(key, value)): 直接操作 Map。


    失效策略:


    并发: ConcurrentHashMap 保证并发安全。写操作较多时注意锁竞争。


    淘汰策略 (Eviction Policy): 当缓存满时(或接近满时)需要淘汰数据。常见策略:


    高级考虑: 缓存击穿、雪崩、穿透的应对策略(加锁、布隆过滤器等)。



    定时失效: 使用 ScheduledExecutorService 或 Timer(不推荐)定期扫描清除过期项。缺点: 不及时,占用资源。


    惰性失效: 在 get(key) 时检查是否过期,过期则删除并返回 null/重新加载。缺点: 可能积累大量过期数据。


    访问顺序失效 (LRU/LFU): 结合 LinkedHashMap (覆盖 removeEldestEntry) 或使用支持淘汰策略的缓存库。最佳实践:使用库。



    LRU (Least Recently Used): 淘汰最久未使用的。


    LFU (Least Frequently Used): 淘汰使用频率最低的。


    FIFO (First In First Out): 淘汰最早进入的。


    Random: 随机淘汰。



    核心点: 快速访问、数据一致性(弱)、内存管理、并发。


    方案:


    答题要点: 优先推荐使用成熟缓存库 (Caffeine > Guava Cache);说明核心使用 ConcurrentHashMap;解释失效和淘汰策略的必要性和常见实现方式;提及缓存异常情况的应对(加分项)。



设计与建模场景


  1. 场景:设计一个停车场管理系统 (Parking Lot System)。


    入场 (parkVehicle(Vehicle v)):


    出场 (exitVehicle(Ticket t)):



    ParkingLot: 管理多个 ParkingFloor 或多个 ParkingSpot。总容量,可用计数。


    ParkingFloor: (可选) 管理本层的 ParkingSpot


    ParkingSpot: 停车位。属性:编号、类型(小型、中型、大型、残疾人位)、是否可用、关联的 Vehicle


    Vehicle: 车辆。属性:车牌号、类型(对应停车位类型)。


    Ticket: 停车票。属性:票据号、入场时间、关联的车位号、关联的车辆车牌号。


    EntryPanel: 入口面板。分配车位、打印票。


    ExitPanel: 出口面板。计算费用、收费、释放车位。



    核心点: 对象建模、状态管理、规则处理。


    关键类和对象:


    核心流程:


    答题要点: 清晰定义核心类和关系;描述入场和出场的关键步骤;考虑车位类型匹配;考虑并发访问(如多个入口/出口)时使用同步或并发集合;可扩展性(不同计费规则、多楼层)。



    寻找可用且类型匹配的 ParkingSpot


    标记车位为占用,关联车辆。


    创建 Ticket 记录入场时间和车位。


    更新 ParkingLot 可用计数。



    根据 Ticket 找到车位和车辆。


    计算停车费(基于入场时间和费率规则)。


    收费。


    释放车位(标记可用,解除车辆关联)。


    更新 ParkingLot 可用计数。



  2. 场景:设计一个简单的在线购物车 (Shopping Cart)。


    数据结构:


    核心操作:


    存储:


    并发考虑: 同一用户在不同设备/标签页操作购物车?通常通过用户会话隔离。数据库操作需考虑并发更新(乐观锁)。


    其他: 商品价格变动如何处理?(通常下单时锁定价格,购物车展示实时价格但下单需校验)。



    Cart: 代表一个购物车。属性:用户标识(用户登录后关联用户 ID;未登录用 SessionID)、List<CartItem>


    CartItem: 购物车项。属性:商品 ID (productId)、商品名称、单价 (price)、数量 (quantity)、小计(可计算)。



    addItem(Product product, int quantity): 添加商品项。如果购物车已有该商品,增加数量;否则新增项。


    updateItemQuantity(String productId, int newQuantity): 修改某商品数量。数量为 0 时移除该项。


    removeItem(String productId): 移除指定商品项。


    getCartTotal(): 计算购物车总金额(遍历所有 CartItem 计算小计并求和)。


    clearCart(): 清空购物车。



    用户未登录: 存储在 HttpSession 中(键值对,如 session.setAttribute("cart", cartObject))。


    用户已登录: 可以将会话中的购物车合并到数据库(关联用户 ID)中,或直接从数据库加载。后续操作持久化到数据库。



    核心点: 状态管理、会话管理、数据结构。


    方案:


    答题要点: 定义 Cart 和 CartItem 结构;说明核心操作方法;区分登录/未登录状态的存储策略;简述价格一致性问题。



  3. 场景:设计一个日志记录器 (Logger)。要求支持不同级别(DEBUG, INFO, WARN, ERROR),可以输出到控制台或文件。


    接口 Logger:


    日志级别 Level: DEBUG < INFO < WARN < ERROR


    抽象 Appender (或 Handler): 负责日志的实际输出目的地。


    Logger 实现:


    Logger 获取: 通常通过一个 LoggerFactory 获取(单例或静态方法),工厂内部管理 Logger 实例(按名称缓存)。


    配置: 通过配置文件(XML, Properties)设置 Logger 级别、Appender 类型和参数(文件路径、格式等)。


    日志格式 (Layout/Formatter): 可抽象一个组件负责将 LoggingEvent 格式化成字符串(如 PatternLayout)。



    方法:debug(String msg)info(String msg)warn(String msg)error(String msg)error(String msg, Throwable t)



    接口/抽象类:append(LoggingEvent event)


    具体实现:ConsoleAppender (输出到 System.out/System.err), FileAppender (输出到文件,需处理文件滚动、归档)。



    持有其日志级别 (Level)。


    持有一个或多个 Appender 的引用。


    当调用日志方法时(如 info(msg)):



    核心点: 设计模式(责任链、抽象工厂等)、扩展性、配置化。


    方案 (参考 SLF4J/Logback 思想):


    答题要点: 强调职责分离(Logger 负责级别过滤和事件创建,Appender 负责输出);说明责任链模式的应用(Logger -> Appenders);提到配置化的重要性;参考主流日志框架设计。



    检查请求级别是否 >= 该 Logger 设置的级别(如 Logger 是 INFO 级别,则 DEBUG 请求被忽略)。


    如果通过,创建 LoggingEvent 对象(包含时间戳、线程名、Logger 名、级别、消息、异常等)。


    将 LoggingEvent 传递给所有关联的 Appender 进行输出。



性能与优化场景


  1. 场景:线上应用出现 OOM (OutOfMemoryError)。如何排查和定位问题?


    找出占用内存最大的对象是哪些? (MAT 的 Dominator Tree, Histogram)


    这些对象被谁引用着?为什么 GC 回收不掉? (MAT 的 Path to GC Roots)


    是否存在内存泄漏 (Memory Leak)? (对象本应被回收但因错误引用导致无法回收,数量持续增长)。查看对象的增长趋势。



    在启动参数中添加 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump.hprof。发生 OOM 时自动生成堆转储文件。


    使用分析工具加载 .hprof 文件:MAT (Memory Analyzer Tool), VisualVM, JProfiler


    关键分析:



    添加参数 -Xloggc:/path/to/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps


    使用 GCViewer, GCEasy 等工具分析。


    关注点: GC 频率、Full GC 频率和耗时、每次 GC 后各区域大小变化、晋升老年代情况、是否因分配担保失败导致 OOM。



    内存泄漏: 静态集合类持有对象引用、未关闭资源(连接、流)、监听器未注销、ThreadLocal 使用不当未清理。


    堆大小设置不合理 (-Xmx): 根本不够用。


    加载过多数据到内存: 大文件、大查询结果未分页。


    代码问题: 死循环创建对象、大对象(数组)频繁创建。



    核心点: JVM 内存模型、监控工具、分析工具、常见原因。


    排查步骤:


    答题要点: 强调 Heap Dump 是关键;熟悉分析工具(MAT);知道如何配置生成 Dump 和 GC 日志;列举常见内存泄漏场景;区分不同 OOM 类型。



    确认错误类型: java.lang.OutOfMemoryError: Java heap space (堆内存不足) 最常见。还有 PermGen space (JDK7-, 方法区), Metaspace (JDK8+, 元空间), Unable to create new native thread (线程过多), GC overhead limit exceeded (GC 效率低下) 等。


    分析堆内存 (Heap Dump):


    分析 GC 日志:


    监控实时状态 (可选): 在 OOM 发生前或复现时使用 jconsolejvisualvmjstat -gcutil <pid> <interval> 监控内存、GC、线程状态。


    常见原因:



  2. 场景:发现某个接口响应时间变慢。如何定位性能瓶颈?


    Profiling (剖析): 使用 VisualVM Profiler, JProfiler, Async Profiler, Arthas 进行 CPU 采样或方法耗时统计。找出 CPU 热点方法或阻塞点。


    日志分析: 在关键路径添加详细耗时日志(使用 System.currentTimeMillis() 或 StopWatch, 或 MDC 记录 TraceId)。关注数据库查询、远程调用、复杂计算的耗时。


    线程分析 (jstack <pid>): 查看线程状态。大量线程处于 BLOCKEDWAITINGTIMED_WAITING 状态可能表示锁竞争或 IO 等待。死锁?



    慢查询日志: 检查数据库(MySQL, PostgreSQL 等)的慢查询日志。分析慢 SQL 的执行计划 (EXPLAIN/EXPLAIN ANALYZE)。


    索引: 检查是否缺少必要索引或索引失效。


    连接池: 连接池是否耗尽?获取连接是否慢?



    远程调用 (RPC/HTTP): 检查下游服务的响应时间(分布式链路追踪如 SkyWalking, Zipkin)。下游服务是否慢?网络延迟?


    缓存: 缓存命中率是否下降?缓存操作是否变慢?


    消息队列: 生产/消费是否积压?



    GC 日志分析 (同 OOM 排查): 频繁 Full GC 会导致 STW (Stop-The-World) 暂停,导致请求卡顿。


    jstat -gcutil: 实时查看 GC 情况。



    CPU: 使用率是否过高?top -Hp <pid> 看哪个线程 CPU 高。


    内存: 是否充足?Swap 使用情况?free -m


    磁盘 IO: 是否瓶颈?iostatiotop


    网络 IO: 带宽是否打满?延迟是否高?sar -n DEVpingtraceroute



    核心点: 性能分析工具、分层排查、监控指标。


    排查步骤 (从应用层到基础设施层):


    答题要点: 强调分层次(代码->DB->外部->JVM->系统)逐步排查;熟练使用性能分析工具(Profiler, jstack, GC 日志分析);关注数据库和外部依赖;结合监控指标。



    确认范围: 是所有请求慢,还是特定请求/参数慢?是持续慢还是偶发慢?


    应用代码分析:


    数据库分析:


    外部依赖分析:


    JVM 分析:


    系统资源监控:


    基础设施: 虚拟机负载、容器调度、网络设备。



框架与系统场景


  1. 场景:在 Spring 项目中,如何设计一个权限控制系统?


    认证 (Authn): 用户是谁?


    授权 (Authz): 用户能做什么?


    RBAC 模型设计 (数据库):


    会话管理: 有状态(Session) vs 无状态(JWT)。



    实现 UserDetailsService 接口加载用户信息(用户名、密码、权限列表)。


    配置认证方式(表单登录、Basic Auth、JWT、OAuth2)。



    基于角色 (RBAC): hasRole('ADMIN')hasAnyRole('USER','EDITOR')


    基于权限 (Permission): hasAuthority('USER:READ')hasAuthority('USER:WRITE')。更细粒度。


    方法级安全: 在 Service 方法上使用 @PreAuthorize@PostAuthorize@Secured 注解。


    URL 级安全: 在配置类 (WebSecurityConfigurerAdapter) 的 configure(HttpSecurity http) 中使用 .antMatchers(...).hasRole(...) 或 .access("hasAuthority('...')")


    动态权限: 实现 FilterInvocationSecurityMetadataSource 从数据库加载 URL-权限映射关系。实现 AccessDecisionManager 或 AccessDecisionVoter 进行投票决策。



    User (用户) - User_Role (用户角色关联) - Role (角色) - Role_Permission (角色权限关联) - Permission (权限:通常对应资源+操作,如 user:delete)。


    权限可直接关联到角色,用户通过角色间接拥有权限。



    核心点: 认证 (Authentication)、授权 (Authorization)、RBAC/ABAC、Spring Security。


    方案 (基于 Spring Security):


    答题要点: 区分认证和授权;介绍 Spring Security 核心组件(UserDetailsServiceFilterChainAccessDecisionManager);说明 RBAC 模型及其表结构;提到方法级和 URL 级配置;了解动态权限概念。



  2. 场景:设计一个分布式 ID 生成器 (Snowflake 算法思路)。


    64 位 ID 结构: 0 | 41位时间戳 (毫秒) | 5位数据中心ID | 5位机器ID | 12位序列号


    组成部分:


    生成过程 (单机):


    优点: 本地生成,无中心节点,性能高;ID 趋势递增;可读性好(包含时间戳、机器信息)。


    缺点: 依赖机器时钟(时钟回拨问题);机器 ID 需要配置(可通过 Zookeeper/Etcd 等分配)。



    符号位 (1 bit): 恒为 0(表示正数)。


    时间戳 (41 bits): 当前时间戳(毫秒级)减去一个自定义纪元 (epoch, 如 2020-01-01)。可用约 69 年。


    数据中心 ID (5 bits): 支持最多 2^5 = 32 个数据中心。


    机器 ID (5 bits): 每个数据中心支持最多 2^5 = 32 台机器。


    序列号 (12 bits): 同一毫秒内同一机器上的计数器。支持每台机器每毫秒生成 2^12 = 4096 个 ID。



    序列号 sequence = (sequence + 1) & sequenceMask (掩码,低 12 位全 1)。


    如果 sequence == 0(表示当前毫秒序列号用完),则循环等待到下一毫秒,重置 sequence



    核心点: 全局唯一、趋势递增、高性能、高可用、分布式。


    Snowflake 方案 (Twitter):


    答题要点: 清晰描述 Snowflake 的 64 位结构;说明每一部分的含义和作用;详细描述生成算法的步骤(特别是时间戳比较和序列号处理);强调时钟回拨问题及其应对;知道其优缺点和适用场景。可提其他方案(UUID, Redis Incr, DB Ticket Table, Leaf, TinyId)做对比。



    获取当前时间戳 timestamp (毫秒)。


    如果当前时间戳 < 上次生成的时间戳,说明时钟回拨,需要处理(等待、报错、使用备用机制)。


    如果当前时间戳 == 上次生成的时间戳:


    如果当前时间戳 > 上次生成的时间戳,重置 sequence 为 0(或一个随机起始值)。


    记录上次时间戳 lastTimestamp = 当前时间戳。


    拼接各部分:(timestamp - epoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence



问题解决与行为场景


  1. 场景:你在代码审查 (Code Review) 中发现同事的代码存在潜在的性能问题(如循环内执行数据库查询)。你会如何处理?


    核心点: 沟通技巧、团队协作、解决问题导向。


    处理步骤:


    答题要点: 强调私下、友好、建设性;对事不对人;清晰指出问题+解释原因+给出建议;倾听和协作;最终目的是写出更好的代码。



    私下沟通: 优先选择私下、友好的方式沟通(IM、面对面),避免在公共评论中直接指责。


    描述事实,而非评价人: “我在看这块代码时,注意到在 for 循环里调用了 userDao.getById(),每次循环都会查一次数据库...”。


    解释潜在影响: “这可能会在数据量大的时候导致数据库查询次数暴增,成为性能瓶颈。”


    提出建设性建议: “我们可以考虑在循环外面一次性把需要的用户数据都查出来(比如根据 ID 列表批量查询 userDao.getByIds(List ids)),然后在循环里使用内存数据。” 或者 “看看业务逻辑是否允许重构避免循环内查询?”


    提供依据/示例 (可选): 如果方便,可以分享一个优化后的伪代码片段或相关文档链接。


    倾听对方观点: 了解同事当时的考虑,是否有特殊原因。


    达成共识: 共同讨论最佳解决方案,并确认修改。


    Code Review 工具中评论: 在确认沟通后,可以在 Review 工具中正式记录这个讨论和建议。



  2. 场景:线上系统突然报警,CPU 使用率飙升到 100%。你作为值班人员,如何快速响应和排查?


    CPU: top -Hp <pid> (找占用 CPU 高的线程 PID) -> 将 PID 转为 16 进制 -> jstack <pid> > jstack.log (看该线程在做什么)。


    内存: jmap -dump:live,format=b,file=heap.hprof <pid> (抓 Heap Dump,谨慎使用,可能 STW)。


    GC: jstat -gcutil <pid> 1000 5 (每隔 1 秒打印 1 次 GC 情况,共 5 次)。


    线程: jstack <pid> > jstack.log (查看线程栈,找死锁、大量 WAITING/BLOCKED 线程)。



    查看 top -Hp 和 jstack 结果,定位热点线程在执行什么代码(看线程栈)。


    如果是 Full GC 频繁导致,分析 GC 日志。


    如果是死循环,查看对应代码。



    重启: 快速恢复服务的最常用方法(但会丢失现场,应在保留现场后做)。


    回滚: 如果是最近发布导致,考虑回滚到上一个稳定版本。


    扩容/隔离: 增加实例分担负载,或隔离问题实例。


    限流/降级: 保护核心链路,避免雪崩。



    核心点: 应急响应流程、故障排查思路、工具使用。


    响应步骤:


    答题要点: 强调保留现场的重要性(top -Hp + jstack 是第一步);熟悉关键诊断命令;区分快速缓解措施和根因排查;体现应急处理流程(确认->止损->恢复->复盘)。



    确认报警: 登录监控系统查看具体指标(CPU、内存、网络、磁盘、GC、应用指标、上下游依赖)是否确实异常。排除误报。


    初步定位影响范围: 是单台机器还是集群?影响哪些功能?用户感知如何?


    保留现场 (关键): 尽快抓取能帮助定位问题的快照信息,避免重启后丢失:


    分析快照信息:


    尝试缓解 (如果可能且风险可控):


    深入排查根因: 利用保留的快照和日志,结合代码进行深入分析(如分析 Heap Dump)。


    修复和恢复: 找到根因后,修复代码、配置或基础设施问题,并验证恢复。


    复盘: 记录故障时间线、原因、处理过程、改进措施。



  3. 场景:项目需要引入一项你不太熟悉的新技术。你会如何着手学习和评估?


    成熟度: 是稳定版还是 Beta/Alpha?生产环境使用案例?


    学习曲线: 团队掌握需要多久?是否有专家?


    维护成本: 升级、Bug 修复、社区支持力度。


    兼容性: 与现有系统(JDK 版本、框架、中间件)是否兼容?


    性能开销: 引入后对系统性能的影响?



    核心点: 学习能力、方法论、风险评估。


    步骤:


    答题要点: 体现系统性学习路径(文档->实践->社区->资源);强调需求驱动;突出风险评估意识(成熟度、成本、兼容性);体现分享和团队协作。



    明确需求和目标: 为什么需要这项技术?要解决什么具体问题?(性能提升、功能需求、降低成本?)替代现有方案的优势?


    官方文档是起点: 阅读官方文档(Getting Started, Concepts, Reference),了解核心概念、特性和最佳实践。


    实践出真知: 动手搭建 Demo 或 POC (Proof of Concept),验证核心功能是否满足需求,感受易用性。


    社区与生态: 查看 GitHub Stars/Issues/PRs、Stack Overflow 活跃度、官方论坛。社区活跃度和支持度很重要。


    学习资源: 查找高质量的博客、教程、视频课程、书籍(官方推荐或知名作者)。


    对比评估: 如果有竞品,进行对比分析(功能、性能、成熟度、社区、学习曲线、License、与现有技术栈集成度)。


    风险评估:


    分享与决策: 将学习成果、Demo、评估结果(特别是收益和风险)整理成文档或演示,与团队和 Leader 讨论,共同决策是否引入。



Java 面试场景题

基础概念类

解释 Java 中的多态性,并举例说明运行时多态的实现方式。

String、StringBuffer 和 StringBuilder 的区别是什么?分别在什么场景下使用?

集合框架

HashMap 的工作原理是什么?如何处理哈希冲突?

比较 ArrayList 和 LinkedList 的性能差异,说明各自适用场景。

并发编程

如何实现线程安全?列举至少三种方式并分析优缺点。

解释 volatile 关键字的作用,它与 synchronized 有何区别?

JVM 相关

描述 JVM 内存模型,哪些区域是线程共享的?

哪些情况会导致 Java 内存泄漏?如何检测和避免?

设计模式

如何在 Spring 中实现单例模式?确保线程安全的方法有哪些?

观察者模式的适用场景是什么?请用代码示例说明实现方式。

异常处理

检查型异常和非检查型异常的区别?各自的处理策略是什么?

实战问题

系统出现 OutOfMemoryError,有哪些排查步骤和解决方案?

如何设计一个分布式 ID 生成器?需要考虑哪些因素?

框架相关

Spring Bean 的生命周期是怎样的?哪些扩展点可以干预这个过程?

MyBatis 中 #{}和 ${}的区别是什么?如何防止 SQL 注入?

算法与数据结构

实现 LRU 缓存机制,要求时间复杂度为 O(1)。

找出数组中第 K 大的元素,至少给出两种解法并分析复杂度。

系统设计

设计一个秒杀系统,重点说明如何解决超卖和高并发问题。

如何保证微服务架构下的数据一致性?

每个问题都应包含:


  • 核心概念清晰表达


  • 实际应用场景说明


  • 必要时提供代码片段或架构图


  • 性能优化或异常处理方案


  • 与其他技术的对比分析

Java 面试场景题问题及答案


包含内容过多,只做了简单的章节截图介绍,每个章节都有更加细化的内容。







用户头像

公众号:程序员高级码农 2022-07-03 加入

公众号:程序员高级码农

评论

发布
暂无评论
十年磨一剑,必出精品——Java面试常见场景题及参考答案!_Java_程序员高级码农_InfoQ写作社区