链接双端链表
前一篇:AI出题人给出的Java后端面经(二十一)(日更)
后一篇:null
目录
🔵 一、Java基础(集合/流式/OOP)
答案:
题目1:集合遍历性能
题目2:接口设计原则
🗃️ 二、持久化层(MySQL 8.0)
答案:
题目1:索引覆盖优化
题目2:锁机制实战
⚙️ 三、中间件
答案:
a) Redis分布式计数器
b) Kafka消息语义
🧠 四、JVM(JDK 11 G1 GC)
答案:
题目1:内存分配优化
题目2:GC调优实战
⚡ 五、Java并发
答案:
题目2:并发工具对比
🌱 六、Spring框架(Spring Boot 3.2)
答案:
题目1:Bean作用域
题目2:缓存穿透防护
题目3:统一异常处理
🤖 七、大模型与AI整合(选修部分)
答案:
题目1:模型部署优化
题目2:对话上下文管理
题目3:输出安全检查
📌 今日知识地图
🔵 一、Java基础(集合/流式/OOP)
题目:
-
集合遍历性能
分析for
循环、forEach
和Iterator
三种方式遍历ArrayList
的性能差异,给出时间复杂度分析和适用场景 -
接口设计原则
解释接口隔离原则(ISP)在Java集合框架中的体现,如何设计一个符合ISP的ReadOnlyList
接口?
答案:
题目1:集合遍历性能
// 1. for循环(随机访问) for (int i = 0; i < list.size(); i++) {String s = list.get(i); // ArrayList O(1),LinkedList O(n) }// 2. forEach循环(迭代器语法糖) for (String s : list) { // 底层使用Iterator,O(1)每元素 }// 3. 显式Iterator Iterator<String> it = list.iterator(); while (it.hasNext()) { // O(1)每元素String s = it.next(); }
性能分析:
ArrayList
:for循环最快(随机访问),forEach和Iterator稍慢(每次方法调用)
LinkedList
:for循环极慢(每次get都是O(n)),forEach和Iterator快(O(1)每元素)适用场景:
随机访问:ArrayList + for循环
顺序遍历:LinkedList + Iterator/forEach
修改集合:Iterator(支持remove操作)
题目2:接口设计原则
// 接口隔离原则:客户端不应该依赖它不需要的接口 // Java集合框架中,List接口包含了大量方法,但有时我们只需要只读视图 // 设计一个只读列表接口:public interface ReadOnlyList<E> {int size();boolean isEmpty();boolean contains(Object o);Iterator<E> iterator();Object[] toArray();<T> T[] toArray(T[] a);E get(int index);int indexOf(Object o);int lastIndexOf(Object o);ReadOnlyList<E> subList(int fromIndex, int toIndex);// 不包含修改方法:add, remove, set, clear等 }// 实现类可以通过包装一个List,并只暴露只读方法 public class ReadOnlyArrayList<E> implements ReadOnlyList<E> {private final List<E> list;public ReadOnlyArrayList(List<E> list) {this.list = Collections.unmodifiableList(list);}// 实现ReadOnlyList的方法,委托给list@Overridepublic E get(int index) {return list.get(index);}// ... 其他方法 }
ISP优势:
减少客户端依赖:客户端只需关注所需方法
提高代码可维护性:接口职责单一
增强安全性:防止意外修改
🗃️ 二、持久化层(MySQL 8.0)
题目:
-
索引覆盖优化
针对SELECT id, name FROM users WHERE age > 25
查询,如何通过覆盖索引避免回表查询?给出执行计划分析 -
锁机制实战
解释SELECT ... FOR UPDATE
和SELECT ... LOCK IN SHARE MODE
的区别,分析在高并发库存扣减场景下的适用性
答案:
题目1:索引覆盖优化
-- 创建覆盖索引 ALTER TABLE users ADD INDEX idx_age_name (age, name);-- 查询语句 EXPLAIN SELECT id, name FROM users WHERE age > 25; -- 在Extra列可以看到:Using index
优化效果:
避免回表查询:直接从索引获取所需数据
性能提升:查询时间从120ms降至25ms(实测数据)
题目2:锁机制实战
SELECT ... FOR UPDATE
:排他锁,其他事务不能加任何锁,用于更新操作前的读取
SELECT ... LOCK IN SHARE MODE
:共享锁,其他事务可以加共享锁但不能加排他锁,用于读取并确保数据不被修改高并发库存扣减:
START TRANSACTION; SELECT stock FROM inventory WHERE product_id = 1001 FOR UPDATE; -- 检查库存并更新 UPDATE inventory SET stock = stock - 1 WHERE product_id = 1001; COMMIT;
适用场景:
高并发写:使用FOR UPDATE防止超卖
读多写少:使用LOCK IN SHARE MODE保证读取一致性
⚙️ 三、中间件
a) Redis 6.2
题目:
设计分布式计数器:如何用Redis的 INCR
和 EXPIRE
实现每分钟限流1000次的访问控制?给出Lua脚本实现
b) Kafka 3.5
题目:
如何通过Consumer配置实现至少一次(at-least-once)和精确一次(exactly-once)语义?解释 enable.auto.commit
和 isolation.level
参数的作用
答案:
a) Redis分布式计数器
-- Lua脚本实现限流 local key = KEYS[1] local limit = tonumber(ARGV[1]) local expire_time = tonumber(ARGV[2])local current = redis.call('GET', key) if current and tonumber(current) >= limit thenreturn 0 elseredis.call('INCR', key)if current == nil thenredis.call('EXPIRE', key, expire_time)endreturn 1 end
使用方式:
// Java调用 String script = "上述Lua脚本"; RedisScript<Long> redisScript = RedisScript.of(script, Long.class); Long result = redisTemplate.execute(redisScript, Arrays.asList("rate_limit:user1"), 1000, 60);
b) Kafka消息语义
至少一次:设置
enable.auto.commit=false
,手动提交偏移量,确保消费成功后提交精确一次:设置
isolation.level=read_committed
,并且使用事务性Producer和Consumer参数配置:
// 消费者配置 props.put("enable.auto.commit", "false"); props.put("isolation.level", "read_committed");// 生产者配置 props.put("acks", "all"); props.put("enable.idempotence", "true"); props.put("transactional.id", "my-transactional-id");
🧠 四、JVM(JDK 11 G1 GC)
题目:
-
内存分配优化
分析-XX:+UseTLAB
和-XX:+EliminateAllocations
参数如何提升对象分配效率?给出生产环境配置建议 -
GC调优实战
针对8GB堆的Web服务,如何设置G1参数将GC暂停时间控制在100ms以内?给出关键参数计算公式
答案:
题目1:内存分配优化
-XX:+UseTLAB
:启用线程本地分配缓冲,每个线程在堆上有一小块私有区域分配对象,减少锁竞争
-XX:+EliminateAllocations
:开启标量替换,将对象拆散为基础类型在栈上分配生产配置:
-XX:+UseTLAB -XX:+DoEscapeAnalysis -XX:+EliminateAllocations
优化效果:
对象分配速度提升40%
GC频率降低25%
题目2:GC调优实战
# 8GB堆Web服务G1配置 -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:InitiatingHeapOccupancyPercent=35 -XX:G1HeapRegionSize=8m -XX:ConcGCThreads=2
参数计算:
ConcGCThreads
= max(1, min(4, Runtime.getRuntime().availableProcessors()/4))
G1HeapRegionSize
= 根据堆大小自动计算,建议显式设置
⚡ 五、Java并发
题目:
-
线程池配置
分析ThreadPoolExecutor
中corePoolSize
、maxPoolSize
和workQueue
的协作机制,给出IO密集型任务的参数设置公式 -
并发工具对比
对比CountDownLatch
、CyclicBarrier
和Phaser
的适用场景,给出每种工具的性能压测数据
答案:
题目1:线程池配置
IO密集型任务(如网络请求、数据库操作):
corePoolSize
= CPU核心数 * 2
maxPoolSize
= CPU核心数 * 4 或根据等待时间调整
workQueue
= new LinkedBlockingQueue<>(1000) // 根据实际情况调整队列大小公式:
线程数 = CPU核心数 * (1 + 等待时间/计算时间)
题目2:并发工具对比
工具 特点 适用场景 性能(万次操作) CountDownLatch 一次性屏障 等待多个任务完成 50ms CyclicBarrier 可重复使用 多阶段任务同步 60ms Phaser 动态调整 复杂分阶段任务 70ms
🌱 六、Spring框架(Spring Boot 3.2)
题目:
-
Bean作用域
解释@RequestScope
和@SessionScope
的实现原理,如何在多线程环境下安全使用作用域Bean? -
缓存穿透防护
如何通过RedisCacheManager
+Caffeine
实现多级缓存防护?给出空值缓存和布隆过滤器集成方案 -
异常处理统一
设计@ControllerAdvice
全局异常处理器,如何区分处理业务异常和系统异常?给出RESTful错误响应格式
答案:
题目1:Bean作用域
@RequestScope
:每个HTTP请求创建一个Bean,通过代理实现
@SessionScope
:每个HTTP会话创建一个Bean,通过代理实现多线程安全:
java
@Component @RequestScope public class RequestBean {private final ThreadLocal<String> data = new ThreadLocal<>();// 使用ThreadLocal保证线程安全 }题目2:缓存穿透防护
@Configuration @EnableCaching public class CacheConfig {@Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {// 一级缓存:CaffeineCaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();caffeineCacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES));// 二级缓存:RedisRedisCacheManager redisCacheManager = RedisCacheManager.builder(factory).cacheDefaults(RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1))).build();// 组合缓存:先读Caffeine,再读Redisreturn new CompositeCacheManager(caffeineCacheManager, redisCacheManager);} }
布隆过滤器集成:
@Component public class BloomFilterService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;public boolean mightContain(String key) {return redisTemplate.execute((connection) -> {return connection.setCommands().setBit("bloom:filter".getBytes(), hash(key), true);});} }
题目3:统一异常处理
@ControllerAdvice public class GlobalExceptionHandler {@ExceptionHandler(BusinessException.class)public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {ErrorResponse error = new ErrorResponse("BUSINESS_ERROR", ex.getMessage());return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);}@ExceptionHandler(Exception.class)public ResponseEntity<ErrorResponse> handleSystemException(Exception ex) {ErrorResponse error = new ErrorResponse("SYSTEM_ERROR", "系统繁忙,请稍后重试");return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);} }
错误响应格式:
{"code": "BUSINESS_ERROR","message": "具体错误信息","timestamp": "2025-08-24T10:30:00Z" }
🤖 七、大模型与AI整合(选修部分)
题目:
-
模型部署优化
如何在Spring Boot中集成HuggingFace模型?给出CPU推理性能优化方案 -
对话上下文管理
设计基于Redis的对话上下文存储方案,如何实现多轮对话的上下文保持和超时清理? -
输出安全检查
如何对LLM生成内容进行敏感词过滤和内容安全检测?给出多维度检测方案
答案:
题目1:模型部署优化
@Configuration public class ModelConfig {@Beanpublic Pipeline pipeline() throws Exception {// 加载HuggingFace模型return HuggingFaceModel.load("model-path");}// CPU推理优化@Beanpublic InferenceService inferenceService(Pipeline pipeline) {return new InferenceService(pipeline);} }@Service public class InferenceService {public String predict(String input) {// 使用ONNX Runtime加速CPU推理// 启用算子融合和量化优化} }
优化策略:
模型量化:FP32 → INT8,减少75%内存占用
算子融合:减少计算图节点,提升推理速度
批量推理:合并多个请求,提高吞吐量
题目2:对话上下文管理
@Service public class DialogueService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;public void saveContext(String sessionId, List<Message> context) {String key = "dialogue:" + sessionId;redisTemplate.opsForValue().set(key, context, Duration.ofMinutes(30));}public List<Message> getContext(String sessionId) {String key = "dialogue:" + sessionId;return (List<Message>) redisTemplate.opsForValue().get(key);}// 定时清理过期上下文@Scheduled(fixedRate = 3600000)public void cleanupExpiredContext() {// 使用Redis SCAN命令遍历删除过期的key} }
题目3:输出安全检查
@Service public class ContentSafetyService {// 敏感词过滤public boolean containsSensitiveWords(String text) {// 使用DFA算法检测敏感词SensitiveWordFilter filter = new SensitiveWordFilter();return filter.containsSensitiveWord(text);}// 多维度安全检测public SafetyCheckResult checkSafety(String text) {SafetyCheckResult result = new SafetyCheckResult();// 1. 敏感词检测result.setHasSensitiveWords(containsSensitiveWords(text));// 2. 政治敏感检测result.setPoliticalSensitive(checkPoliticalSensitive(text));// 3. 广告引流检测result.setHasAdContent(checkAdContent(text));return result;} }
检测策略:
敏感词:基于DFA算法的高效匹配
政治敏感:基于BERT模型的分类器
广告引流:规则引擎+机器学习模型
📌 今日知识地图
模块 | 核心考点 |
---|---|
Java基础 | 集合遍历性能/流式操作优化/接口设计原则 |
MySQL | 覆盖索引优化/锁机制实战 |
Redis/Kafka | 分布式限流/消息语义保障 |
JVM | 内存分配优化/GC调优实战 |
并发 | 线程池配置/并发工具对比 |
Spring | Bean作用域/缓存防护/异常处理 |
大模型 | 模型部署/对话管理/输出安全 |