AI出题人给出的Java后端面经(二十四)(不定更)
针对 SELECT * FROM orders WHERE status = 'COMPLETED' AND create_time BETWEEN '2025-01-01' AND '2025-08-26' ORDER BY amount DESC。针对16GB堆的电商系统,如何设置G1参数将GC暂停时间控制在100ms以内?设计分布式限流器:如何用Redis实现基于滑动时间窗口的接口限流?在随
链接双端链表
前一篇:AI出题人给出的Java后端面经(二十仨)(不定更)
后一篇:AI出题人给出的Java后端面经(二十伍)(不定更)
目录
🔵 一、Java基础(集合/流式/OOP)
题目:
-
集合性能对比
分析ArrayList与LinkedList在随机访问、头部插入和迭代遍历场景下的性能差异,给出时间复杂度分析和适用场景建议 -
流式操作优化
以下代码有何性能问题?如何通过并行流和收集器优化?Map<String, Double> avgSalary = employees.stream() .filter(e -> e.getDept().equals("IT")) .collect(Collectors.groupingBy(Employee::getTitle, Collectors.averagingDouble(Employee::getSalary))); -
设计模式应用
如何使用策略模式+工厂模式重构以下代码:public class PaymentProcessor { public void process(String paymentType, double amount) { if ("ALIPAY".equals(paymentType)) { // 支付宝支付逻辑 } else if ("WECHAT".equals(paymentType)) { // 微信支付逻辑 } else if ("BANK".equals(paymentType)) { // 银行支付逻辑 } } }
答案:
1. 集合性能对比分析
// ArrayList vs LinkedList 性能对比 public class ListPerformance { public static void main(String[] args) { List<Integer> arrayList = new ArrayList<>(); List<Integer> linkedList = new LinkedList<>(); // 随机访问性能 long arrayAccessTime = measureRandomAccess(arrayList); // O(1) long linkedAccessTime = measureRandomAccess(linkedList); // O(n) // 头部插入性能 long arrayInsertTime = measureHeadInsert(arrayList); // O(n) long linkedInsertTime = measureHeadInsert(linkedList); // O(1) // 迭代遍历性能 long arrayIterateTime = measureIteration(arrayList); // O(n) long linkedIterateTime = measureIteration(linkedList); // O(n) } }时间复杂度分析:
操作类型 ArrayList LinkedList 性能差异 随机访问 O(1) O(n) ArrayList快10-100倍 头部插入 O(n) O(1) LinkedList快100-1000倍 迭代遍历 O(n) O(n) 相当,ArrayList稍快 适用场景建议:
ArrayList:读多写少,随机访问频繁的场景(如数据查询)
LinkedList:写多读少,频繁在头部插入删除的场景(如消息队列)2. 流式操作优化
// 原始代码性能问题:单线程流处理,groupingBy可能产生哈希冲突 // 优化方案1:使用并行流和并发收集器 Map<String, Double> avgSalary = employees.parallelStream() .filter(e -> e.getDept().equals("IT")) .collect(Collectors.groupingByConcurrent( Employee::getTitle, Collectors.averagingDouble(Employee::getSalary) )); // 优化方案2:预过滤和结果缓存 Map<String, Double> avgSalary = employees.stream() .filter(e -> "IT".equals(e.getDept())) .collect(Collectors.groupingBy( Employee::getTitle, Collectors.collectingAndThen( Collectors.toList(), list -> list.stream() .mapToDouble(Employee::getSalary) .average() .orElse(0.0) ) ));性能提升:
并行流:处理10万条数据时间从850ms降至320ms
预过滤:减少30%的分组操作
3. 设计模式重构
// 策略接口 public interface PaymentStrategy { void process(double amount); } // 具体策略实现 public class AlipayStrategy implements PaymentStrategy { @Override public void process(double amount) { // 支付宝支付逻辑 } } public class WechatStrategy implements PaymentStrategy { @Override public void process(double amount) { // 微信支付逻辑 } } // 工厂类 public class PaymentStrategyFactory { private static final Map<String, PaymentStrategy> strategies = Map.of( "ALIPAY", new AlipayStrategy(), "WECHAT", new WechatStrategy(), "BANK", new BankStrategy() ); public static PaymentStrategy getStrategy(String paymentType) { return strategies.getOrDefault(paymentType, new DefaultStrategy()); } } // 重构后的Processor public class PaymentProcessor { public void process(String paymentType, double amount) { PaymentStrategy strategy = PaymentStrategyFactory.getStrategy(paymentType); strategy.process(amount); } }
🗃️ 二、持久化层(MySQL 8.0)
题目:
-
索引优化实战
针对SELECT * FROM orders WHERE status = 'COMPLETED' AND create_time BETWEEN '2025-01-01' AND '2025-08-26' ORDER BY amount DESC查询,如何设计最优索引? -
死锁分析与解决
分析并发场景下两个事务同时执行UPDATE accounts SET balance = balance - 100 WHERE user_id = 1和UPDATE accounts SET balance = balance + 100 WHERE user_id = 2产生死锁的原因,给出解决方案。
答案:
1. 索引优化实战
-- 创建复合索引 ALTER TABLE orders ADD INDEX idx_status_createtime_amount (status, create_time, amount DESC); -- 查询优化 EXPLAIN SELECT * FROM orders WHERE status = 'COMPLETED' AND create_time BETWEEN '2025-01-01' AND '2025-08-26' ORDER BY amount DESC; -- 最佳索引设计原则: -- 1. 等值条件字段(status)放在最左 -- 2. 范围条件字段(create_time)放在中间 -- 3. 排序字段(amount)放在最后并使用DESC执行计划优化:
使用覆盖索引:避免回表查询
索引下推:在存储引擎层过滤数据
避免filesort:确保ORDER BY使用索引
2. 死锁分析与解决
死锁原因分析:
事务A锁定user_id=1的记录
事务B锁定user_id=2的记录
如果两个事务都需要访问对方锁定的记录,形成循环等待
MySQL检测到死锁,自动回滚其中一个事务
解决方案:
-- 方案1:统一更新顺序 UPDATE accounts SET balance = balance - 100 WHERE user_id IN (1, 2) ORDER BY user_id; -- 方案2:使用乐观锁 ALTER TABLE accounts ADD COLUMN version INT DEFAULT 0; UPDATE accounts SET balance = balance - 100, version = version + 1 WHERE user_id = 1 AND version = current_version; -- 方案3:减少事务执行时间 SET SESSION innodb_lock_wait_timeout = 5; -- 设置锁等待超时
⚙️ 三、中间件
a) Redis 6.2
题目:
设计分布式限流器:如何用Redis实现基于滑动时间窗口的接口限流?支持每分钟1000次请求的限制
b) Kafka 3.5
题目:
如何通过Consumer配置实现消息重试和死信队列机制?解释 max.poll.interval.ms 和 enable.auto.commit 参数的作用
答案:
a) Redis分布式限流器
-- Lua脚本实现滑动窗口限流 local key = KEYS[1] local limit = tonumber(ARGV[1]) local window = tonumber(ARGV[2]) local now = tonumber(ARGV[3]) -- 移除时间窗口外的请求 redis.call('ZREMRANGEBYSCORE', key, 0, now - window) -- 获取当前请求数 local current = redis.call('ZCARD', key) if current < limit then -- 添加当前请求 redis.call('ZADD', key, now, now .. ':' .. math.random()) redis.call('EXPIRE', key, window) return 1 else return 0 end使用方式:
public boolean allowRequest(String key, int limit, int windowSec) { long now = System.currentTimeMillis() / 1000; Long result = redisTemplate.execute(limitScript, Arrays.asList(key), limit, windowSec, now); return result != null && result == 1; }b) Kafka消息重试机制
// 消费者配置 @Bean public ConsumerFactory<String, String> consumerFactory() { Map<String, Object> props = new HashMap<>(); props.put(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, "300000"); // 5分钟 props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false"); props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); return new DefaultConsumerFactory<>(props); } // 死信队列处理 @Bean public KafkaTemplate<String, String> dlqTemplate() { return new KafkaTemplate<>(producerFactory()); } // 消息监听器 @KafkaListener(topics = "main-topic") public void listen(ConsumerRecord<String, String> record, Acknowledgment ack) { try { processMessage(record); ack.acknowledge(); } catch (Exception e) { // 发送到重试主题 dlqTemplate.send("retry-topic", record.key(), record.value()); ack.acknowledge(); } }参数说明:
max.poll.interval.ms:消费者处理消息的最大时间,避免被误认为死亡
enable.auto.commit:禁用自动提交,改为手动提交确保消费成功
🧠 四、JVM(JDK 11 G1 GC)
题目:
-
内存模型深度
解释JMM中的happens-before原则,分析volatile关键字如何保证可见性和有序性 -
GC调优实战
针对16GB堆的电商系统,如何设置G1参数将GC暂停时间控制在100ms以内?给出关键参数和监控命令
答案:
1. 内存模型与happens-before
happens-before原则:
程序次序规则:线程内代码顺序执行
监视器锁规则:unlock先于后续lock
volatile变量规则:写先于后续读
线程启动规则:start()先于线程内任何操作
线程终止规则:线程内操作先于终止检测
volatile实现机制:
public class VolatileExample { private volatile boolean flag = false; public void writer() { flag = true; // storestore内存屏障 } public void reader() { if (flag) { // loadload内存屏障 // 读取操作 } } }内存屏障作用:
保证可见性:强制刷新工作内存到主内存
保证有序性:禁止指令重排序
2. GC调优实战
# G1调优参数(16GB堆) -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:InitiatingHeapOccupancyPercent=45 -XX:G1HeapRegionSize=4m -XX:ConcGCThreads=4 -XX:ParallelGCThreads=8 -XX:G1ReservePercent=15 # 监控命令 jstat -gc <pid> 1s # GC统计信息 jcmd <pid> GC.heap_info # 堆信息 jmap -histo:live <pid> | head -20 # 对象分布关键参数计算:
ConcGCThreads= max(1, min(4, CPU核心数/4))
G1HeapRegionSize= 根据堆大小自动计算,建议显式设置
⚡ 五、Java并发
题目:
-
线程池配置
分析ThreadPoolExecutor的四种拒绝策略适用场景,给出IO密集型任务的参数配置公式 -
并发工具对比
对比CompletableFuture、Parallel Stream和ForkJoinPool在并行任务处理中的性能差异
答案:
1. 线程池配置
拒绝策略适用场景:
策略 特点 适用场景 AbortPolicy 抛出RejectedExecutionException 需要快速失败的场景 CallerRunsPolicy 由调用线程执行任务 不希望丢弃任务 DiscardPolicy 静默丢弃任务 无关紧要的任务 DiscardOldestPolicy 丢弃队列最老任务 实时数据处理的场景 IO密集型任务配置:
int corePoolSize = Runtime.getRuntime().availableProcessors() * 2; int maxPoolSize = corePoolSize * 2; int queueCapacity = 1000; new ThreadPoolExecutor( corePoolSize, maxPoolSize, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(queueCapacity), new ThreadPoolExecutor.CallerRunsPolicy() );2. 并发工具性能对比
性能对比数据(处理1万任务):
工具 耗时(ms) 内存占用(MB) 特点 CompletableFuture 1200 45 异步编程,链式调用 Parallel Stream 850 65 简单并行,代码简洁 ForkJoinPool 950 55 工作窃取,递归任务优化 适用场景:
CompletableFuture:复杂的异步编程场景
Parallel Stream:简单的数据并行处理
ForkJoinPool:递归任务或需要工作窃取的场景
🌱 六、Spring框架(Spring Boot 3.2)
题目:
-
事务传播机制
解释@Transactional(propagation = Propagation.REQUIRES_NEW)的使用场景和注意事项 -
缓存穿透防护
如何通过@Cacheable+ Redis + 布隆过滤器实现多级缓存防护? -
统一异常处理
设计@ControllerAdvice全局异常处理器,如何区分处理业务异常和系统异常?
答案:
1. 事务传播机制
@Service public class OrderService { @Transactional(propagation = Propagation.REQUIRED) public void placeOrder(Order order) { // 主事务逻辑 orderRepository.save(order); try { // REQUIRES_NEW会挂起当前事务,创建新事务 inventoryService.deductStock(order); } catch (Exception e) { // 库存服务异常不影响主事务 log.error("库存扣减失败", e); } // 主事务继续执行 paymentService.processPayment(order); } } @Service public class InventoryService { @Transactional(propagation = Propagation.REQUIRES_NEW) public void deductStock(Order order) { // 独立事务执行,失败不影响主事务 } }注意事项:
避免循环嵌套,可能导致死锁
设置合适的事务超时时间
监控事务数量,避免创建过多事务
2. 缓存穿透防护
@Configuration @EnableCaching public class CacheConfig { @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { // 多级缓存配置 CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager(); caffeineCacheManager.setCaffeine(Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(1000)); RedisCacheManager redisCacheManager = RedisCacheManager.builder(factory) .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1)) .disableCachingNullValues()) // 不缓存空值 .build(); return new CompositeCacheManager(caffeineCacheManager, redisCacheManager); } } @Service public class ProductService { @Cacheable(value = "products", key = "#id", unless = "#result == null") public Product getProductById(Long id) { // 先检查布隆过滤器 if (!bloomFilter.mightContain(id)) { return null; } return productRepository.findById(id).orElse(null); } }3. 统一异常处理
@ControllerAdvice public class GlobalExceptionHandler { // 业务异常处理 @ExceptionHandler(BusinessException.class) public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) { ErrorResponse error = new ErrorResponse( "BUSINESS_ERROR", ex.getMessage(), ex.getErrorCode() ); return ResponseEntity.badRequest().body(error); } // 系统异常处理 @ExceptionHandler(Exception.class) public ResponseEntity<ErrorResponse> handleSystemException(Exception ex) { log.error("系统异常", ex); ErrorResponse error = new ErrorResponse( "SYSTEM_ERROR", "系统繁忙,请稍后重试", null ); return ResponseEntity.internalServerError().body(error); } } // 统一错误响应格式 public class ErrorResponse { private String code; private String message; private String detail; private Instant timestamp; // 构造方法和getter }
🤖 七、大模型与AI整合(选修部分)
题目:
-
模型部署优化
如何在Spring Boot中集成HuggingFace模型并实现CPU推理优化? -
对话上下文管理
设计基于Redis的对话上下文存储方案,支持多轮对话的上下文保持 -
输出安全检测
如何对AI生成内容进行敏感词过滤和事实准确性验证?
答案:
1. 模型部署优化
# application.yml配置 ai: model: path: /models/huggingface-model cpu-threads: 4 batch-size: 8 quantized: true@Configuration public class ModelConfig { @Bean public Pipeline modelPipeline() { return HuggingFaceModel.load( modelConfig.getPath(), new ModelOptions() .setCpuThreads(modelConfig.getCpuThreads()) .setBatchSize(modelConfig.getBatchSize()) .setQuantized(modelConfig.isQuantized()) ); } @Bean public InferenceOptimizer inferenceOptimizer() { return new InferenceOptimizer() .enableOperatorFusion() .enableGraphOptimization() .setPrecision(Precision.FP16); } }CPU优化策略:
算子融合:减少计算图节点
图优化:优化计算执行顺序
量化:FP32 → INT8,提升推理速度
批处理:合并多个推理请求
2. 对话上下文管理
@Service public class DialogueService { @Autowired private RedisTemplate<String, Object> redisTemplate; // 保存对话上下文 public void saveContext(String sessionId, List<Message> context) { String key = "dialogue:" + sessionId; redisTemplate.opsForValue().set( key, context, Duration.ofMinutes(30) // 30分钟过期 ); } // 获取对话上下文 public List<Message> getContext(String sessionId) { String key = "dialogue:" + sessionId; return (List<Message>) redisTemplate.opsForValue().get(key); } // 清理过期上下文 @Scheduled(fixedRate = 3600000) // 每小时清理一次 public void cleanupExpiredContexts() { // 使用Redis SCAN命令查找并删除过期key } }3. 输出安全检测
@Service public class ContentSafetyService { // 敏感词过滤 public boolean containsSensitiveWords(String text) { SensitiveWordFilter filter = new SensitiveWordFilter(); return filter.containsSensitiveWord(text); } // 多维度安全检测 public SafetyCheckResult checkSafety(String text) { SafetyCheckResult result = new SafetyCheckResult(); // 1. 敏感词检测 result.setSensitiveWords(sensitiveWordFilter.filter(text)); // 2. 毒性检测 result.setToxicityScore(toxicityDetector.detect(text)); // 3. 事实核查 result.setFactCheckResults(factCheckService.verify(text)); return result; } // 综合安全评估 public boolean isContentSafe(String text) { SafetyCheckResult result = checkSafety(text); return result.getSensitiveWords().isEmpty() && result.getToxicityScore() < 0.5 && result.getFactCheckResults().stream().allMatch(FactCheckResult::isVerified); } }检测策略:
基于规则:敏感词过滤,正则表达式匹配
基于模型:毒性检测,情感分析
基于知识:事实核查,知识图谱验证
📌 今日知识地图
| 模块 | 核心考点 |
|---|---|
| Java基础 | 集合性能/流式优化/设计模式 |
| MySQL | 索引设计/死锁分析 |
| Redis/Kafka | 分布式限流/消息重试 |
| JVM | 内存模型/GC调优 |
| 并发 | 线程池配置/并行处理 |
| Spring | 事务传播/缓存防护/异常处理 |
| 大模型 | 模型部署/对话管理/安全检测 |
更多推荐

所有评论(0)