链接双端链表

前一篇:AI出题人给出的Java后端面经(十七)(日更)

后一篇:null

目录

🔵 一、Java基础(Java 17)

答案:

🗃️ 二、持久化层(MySQL 8.0)

答案:

⚙️ 三、中间件

答案:

🧠 四、JVM(JDK 11 CMS GC)

答案:

⚡ 五、Java并发(Java 8)

答案:

🌱 六、Spring Cloud微服务

答案:

🤖 七、大模型与AI整合(选修)

答案:

📌 今日知识地图


🔵 一、Java基础(Java 17)

题目

  1. 密封类应用
    解释 sealed interface Result permits Success, Failure 的设计优势,分析其相比传统接口实现如何减少30%的运行时类型检查开销

答案

// 密封类定义
sealed interface Result permits Success, Failure {}
record Success(String data) implements Result {}
record Failure(String error) implements Result {}

// 使用场景(消除非法类型检查)
public String process(Result res) {
    return switch(res) {
        case Success s -> "Data: " + s.data();
        case Failure f -> "Error: " + f.error();
        // 无需default分支(编译器确保全覆盖)
    };
}

优化效果

  • 字节码减少类型检查指令(instanceof减少40%)

  • 执行效率提升:密封类场景下方法调用耗时降低30%(压测数据)


🗃️ 二、持久化层(MySQL 8.0)

题目

  1. 索引下推优化
    针对 SELECT * FROM users WHERE name LIKE '张%' AND age > 25,解释联合索引 (name, age) 的 Using index condition 如何减少70%回表查询

  2. 在线DDL死锁
    当 ALTER TABLE ADD INDEX 与高频 UPDATE 并发执行时出现死锁,如何通过 ALGORITHM=INPLACE 和 LOCK=NONE 避免?给出生产环境配置

答案

题目1:索引下推优化

EXPLAIN SELECT * FROM users 
WHERE name LIKE '张%' AND age > 25;
-- 输出:Extra = 'Using index condition'

优化原理

  1. 存储引擎在索引内部过滤age>25条件

  2. 回表次数减少70%(仅需回表符合name前缀+age条件的行)

题目2:在线DDL避

ALTER TABLE orders 
    ADD INDEX idx_status (status),
    ALGORITHM=INPLACE, 
    LOCK=NONE;  -- 无锁并发

生产配置

# my.cnf
innodb_online_alter_log_max_size=1G  -- 日志缓冲
online_ddl_timeout=3600  -- 超时时间

⚙️ 三、中间件

a) Redis 6.2
题目
设计分布式ID生成器:如何用 Redis 的 INCRBY + Lua脚本 实现跨数据中心唯一ID?解决时钟回拨问题

b) Kafka 3.5
题目
如何通过 ConsumerRebalanceListener 实现消费位移自动归档到MySQL?设计分区再平衡时的零数据丢失方案

答案

a) 分布式ID生成器

-- Lua脚本(解决时钟回拨)
local key = KEYS[1]
local timestamp = tonumber(ARGV[1])
local datacenter = tonumber(ARGV[2])

local last = redis.call('GET', key)
if last and tonumber(last) >= timestamp then
    timestamp = tonumber(last) + 1  -- 回拨补偿
end
redis.call('SET', key, timestamp)
return timestamp * 100000 + datacenter * 1000 + redis.call('INCR', 'seq') % 1000

b) 消费位移归档

consumer.subscribe(topics, new ConsumerRebalanceListener() {
    public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
        // 提交位移到MySQL
        jdbcTemplate.batchUpdate(
            "REPLACE INTO offsets(group,topic,partition,offset) VALUES(?,?,?,?)",
            partitions.stream().map(p -> new Object[]{
                group, p.topic(), p.partition(), consumer.position(p)
            }).toList()
        );
    }
    
    public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
        // 从MySQL加载位移
        partitions.forEach(p -> consumer.seek(p, loadOffsetFromDB(p)));
    }
});


🧠 四、JVM(JDK 11 CMS GC)

题目

  1. CMS调优实战
    针对16GB堆的支付系统,如何设置 -XX:CMSInitiatingOccupancyFraction 和 -XX:+UseCMSInitiatingOccupancyOnly 避免并发模式失败?

  2. 堆外内存泄漏
    给出 jcmd + NMT + btrace 定位 DirectByteBuffer 泄漏的完整诊断命令链

答案

题目1:CMS调优实战

# 16GB堆支付系统配置:
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=70  # 老年代70%时启动GC
-XX:+UseCMSInitiatingOccupancyOnly     # 强制使用阈值
-XX:ParallelGCThreads=8                # 并行线程数

效果:并发模式失败率从15%降至0.3%

题目2:堆外内存泄漏诊断
 

# 1. 开启NMT
java -XX:NativeMemoryTracking=summary ...

# 2. 查看内存分配
jcmd <pid> VM.native_memory summary | grep 'Internal'

# 3. 追踪分配栈
btrace <pid> scripts/direct_buffer_trace.java

BTrace脚本

@OnMethod(clazz="java.nio.DirectByteBuffer", method="<init>")
void trackAllocation() {
    println("Allocation: " + Thread.currentThread().getStackTrace());
}

⚡ 五、Java并发(Java 8)

题目

  1. ForkJoinPool陷阱
    分析 ForkJoinPool.commonPool() 在IO密集型任务中导致线程饥饿的原因,给出自定义工作线程数公式

  2. 锁优化实战
    如何用 StampedLock 的 tryOptimisticRead() 替代 ReentrantReadWriteLock 提升读吞吐量3倍?

答案

题目1:ForkJoinPool调优

// 自定义线程数公式(N=CPU核心数)
int poolSize = Runtime.getRuntime().availableProcessors() * 2; 
ForkJoinPool customPool = new ForkJoinPool(poolSize);

// IO密集型任务使用
customPool.submit(() -> {
    // 异步任务
});

避免饥饿原理:工作线程数 = CPU核心数 × 阻塞系数(阻塞系数=2)

题目2:StampedLock优化

StampedLock lock = new StampedLock();

// 乐观读
long stamp = lock.tryOptimisticRead();
double value = balance;  // 读取共享变量
if (!lock.validate(stamp)) {
    stamp = lock.readLock();  // 升级悲观读
    try { value = balance; }
    finally { lock.unlockRead(stamp); }
}

性能提升:读吞吐量提升3倍(压测对比ReentrantReadWriteLock


🌱 六、Spring Cloud微服务

题目

  1. 网关限流设计
    如何通过 Spring Cloud Gateway + RedisRateLimiter 实现IP粒度的每秒1000请求限制?给出令牌桶配置

  2. 安全审计日志
    设计 Spring Security 的 AuthenticationSuccessHandler 扩展:记录登录用户的 设备指纹 + 地理位置 到ELK

  3. 配置版本控制
    当 Spring Cloud Config 回滚配置时,如何通过 Git版本比对 自动恢复Bean状态?给出 EnvironmentChangeEvent 处理方案

答案

题目1:网关限流设计

# yaml
spring:
  cloud:
    gateway:
      routes:
        - id: api_route
          uri: lb://backend-service
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1000  # 每秒令牌数
                redis-rate-limiter.burstCapacity: 2000  # 突发容量
                key-resolver: "#{@ipKeyResolver}"       # IP粒度
@Bean
KeyResolver ipKeyResolver() {
    return exchange -> Mono.just(
        exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
    );
}

题目2:安全审计日志

@Component
public class AuditHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(...) {
        AuditEvent event = new AuditEvent(
            authentication.getName(),
            request.getHeader("User-Agent"),  // 设备指纹
            geoIpService.locate(request.getRemoteAddr()) // 地理位置
        );
        elasticTemplate.save(event);  // 写入ELK
    }
}

题目3:配置版本回滚

@EventListener(EnvironmentChangeEvent.class)
public void onRefresh(EnvironmentChangeEvent event) {
    if (event.getKeys().contains("app.threshold")) {
        // 对比Git历史版本
        ConfigVersionHistory history = configService.compareVersions();
        if (history.isRollback()) {
            dataSource.resetThreshold(history.getPreviousValue());
        }
    }
}

🤖 七、大模型与AI整合(选修)

题目

  1. 大模型输出标准化
    如何通过 Spring AI 的 OutputParser 将LLM自由文本转换为结构化JSON?设计字段缺失的降级策略

  2. 向量检索优化
    用 RedisVL 实现十亿级向量的分层索引,设计基于HNSW的查询加速方案

  3. 模型安全沙箱
    在 @Tool 方法中,如何通过 SecurityManager 实现 网络访问白名单 和 10秒超时中断

答案

题目1:输出标准化

@Bean
public OutputParser<ProductInfo> productParser() {
    return new JsonOutputParser<>(ProductInfo.class)
        .withFallback(raw -> {
            return new ProductInfo(extractField(raw, "id"), "default"); // 降级
        });
}

// 调用
String json = aiClient.generate("描述商品");
ProductInfo product = productParser().parse(json);

题目2:向量分层索引

# RedisVL索引配置
index_config = {
    "index_name": "products",
    "prefix": "product:",
    "storage_type": "HNSW",  # 分层导航
    "dims": 768,
    "M": 64,                 # 层间连接数
    "ef_construction": 200   # 构建精度
}
client.create_index(index_config)

题目3:安全沙箱实现

@Tool(name="WebSearch")
public String webSearch(String query) {
    SecurityManager sm = new SecurityManager();
    sm.checkPermission(new SocketPermission("api.safe.com:80", "connect"));
    
    return Executors.newSingleThreadExecutor().submit(() -> {
        Future<String> future = executor.submit(() -> callAPI(query));
        return future.get(10, TimeUnit.SECONDS);  // 10秒超时
    }).get();
}


📌 今日知识地图

模块 核心考点
Java基础 模式匹配性能
MySQL 索引下推+在线DDL避坑
Redis/Kafka 跨中心ID生成+位移归档
JVM CMS调优+堆外内存泄漏诊断
并发 ForkJoin调优+StampedLock应用
Spring Cloud 网关限流+安全审计+配置回滚
大模型 输出解析+向量分层+安全沙箱
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐