【Java基础】Java 8-21新特性:JDK21 LTS:虚拟线程、模式匹配switch、结构化并发、序列集合(附《思维导图》+《面试高频考点清单》)

文章目录

  • [Java 8-21新特性系统性知识体系:聚焦JDK21 LTS四大核心特性](#Java 8-21新特性系统性知识体系:聚焦JDK21 LTS四大核心特性)
    • 一、Java版本演进全景与LTS战略
      • [1.1 版本时间线与LTS定位](#1.1 版本时间线与LTS定位)
      • [1.2 从Java 8到21的核心演进脉络](#1.2 从Java 8到21的核心演进脉络)
    • [二、Java 8-20关键特性概览(JDK21基础)](#二、Java 8-20关键特性概览(JDK21基础))
      • [2.1 语言特性演进](#2.1 语言特性演进)
      • [2.2 运行时与性能优化](#2.2 运行时与性能优化)
    • [三、JDK21 LTS四大核心特性深度解析](#三、JDK21 LTS四大核心特性深度解析)
      • [3.1 虚拟线程(Virtual Threads,JEP 444,正式特性)](#3.1 虚拟线程(Virtual Threads,JEP 444,正式特性))
        • [3.1.1 传统平台线程的局限性](#3.1.1 传统平台线程的局限性)
        • [3.1.2 虚拟线程的M:N调度模型](#3.1.2 虚拟线程的M:N调度模型)
        • [3.1.3 核心API与使用方式](#3.1.3 核心API与使用方式)
        • [3.1.4 适用场景与最佳实践](#3.1.4 适用场景与最佳实践)
      • [3.2 模式匹配switch(Pattern Matching for switch,JEP 441,正式特性)](#3.2 模式匹配switch(Pattern Matching for switch,JEP 441,正式特性))
        • [3.2.1 传统switch的局限性](#3.2.1 传统switch的局限性)
        • [3.2.2 模式匹配switch的核心能力](#3.2.2 模式匹配switch的核心能力)
        • [3.2.3 语法示例](#3.2.3 语法示例)
        • [3.2.4 与记录模式结合(JEP 440,正式特性)](#3.2.4 与记录模式结合(JEP 440,正式特性))
      • [3.3 结构化并发(Structured Concurrency,JEP 453,预览特性)](#3.3 结构化并发(Structured Concurrency,JEP 453,预览特性))
        • [3.3.1 传统并发编程的问题](#3.3.1 传统并发编程的问题)
        • [3.3.2 结构化并发的核心思想](#3.3.2 结构化并发的核心思想)
        • [3.3.3 核心API与使用方式](#3.3.3 核心API与使用方式)
        • [3.3.4 与传统方案对比](#3.3.4 与传统方案对比)
      • [3.4 序列集合(Sequenced Collections,JEP 431,正式特性)](#3.4 序列集合(Sequenced Collections,JEP 431,正式特性))
        • [3.4.1 传统集合框架的问题](#3.4.1 传统集合框架的问题)
        • [3.4.2 序列集合接口体系](#3.4.2 序列集合接口体系)
        • [3.4.3 核心方法](#3.4.3 核心方法)
        • [3.4.4 使用示例](#3.4.4 使用示例)
    • 四、JDK21其他重要特性
      • [4.1 分代ZGC(Generational ZGC,JEP 439,正式特性)](#4.1 分代ZGC(Generational ZGC,JEP 439,正式特性))
      • [4.2 字符串模板(String Templates,JEP 430,预览特性)](#4.2 字符串模板(String Templates,JEP 430,预览特性))
      • [4.3 未命名模式和变量(Unnamed Patterns and Variables,JEP 443,预览特性)](#4.3 未命名模式和变量(Unnamed Patterns and Variables,JEP 443,预览特性))
      • [4.4 作用域值(Scoped Values,JEP 446,预览特性)](#4.4 作用域值(Scoped Values,JEP 446,预览特性))
    • 五、迁移建议与最佳实践
      • [5.1 分阶段迁移策略](#5.1 分阶段迁移策略)
      • [5.2 常见兼容性问题与解决方案](#5.2 常见兼容性问题与解决方案)
      • [5.3 生产环境最佳实践](#5.3 生产环境最佳实践)
    • 六、总结与未来展望
  • [Java 8-21新特性面试背诵版(JDK21 LTS核心考点)](#Java 8-21新特性面试背诵版(JDK21 LTS核心考点))
    • 一、Java版本演进与LTS战略(面试必问基础)
      • [1.1 LTS版本时间线与核心定位(必背表格)](#1.1 LTS版本时间线与核心定位(必背表格))
      • [1.2 核心演进脉络(一句话总结)](#1.2 核心演进脉络(一句话总结))
    • [二、Java 8-20高频考点速记(每个版本1个核心特性)](#二、Java 8-20高频考点速记(每个版本1个核心特性))
    • 三、JDK21四大核心特性(面试重中之重,占比80%)
      • [3.1 虚拟线程(Virtual Threads,JEP 444,正式)](#3.1 虚拟线程(Virtual Threads,JEP 444,正式))
      • [3.2 模式匹配switch(Pattern Matching for switch,JEP 441,正式)](#3.2 模式匹配switch(Pattern Matching for switch,JEP 441,正式))
      • [3.3 结构化并发(Structured Concurrency,JEP 453,预览)](#3.3 结构化并发(Structured Concurrency,JEP 453,预览))
      • [3.4 序列集合(Sequenced Collections,JEP 431,正式)](#3.4 序列集合(Sequenced Collections,JEP 431,正式))
    • 四、JDK21其他高频考点
    • 五、迁移与最佳实践高频考点
      • [5.1 分阶段迁移策略(必背)](#5.1 分阶段迁移策略(必背))
      • [5.2 虚拟线程最佳实践(必背)](#5.2 虚拟线程最佳实践(必背))
    • 六、面试高频问答TOP10(直接背诵)
  • [Java 8-21新特性一页纸速记版(考前突击专用)](#Java 8-21新特性一页纸速记版(考前突击专用))

Java 8-21新特性系统性知识体系:聚焦JDK21 LTS四大核心特性

一、Java版本演进全景与LTS战略

1.1 版本时间线与LTS定位

Java采用"6个月一个功能版,3年一个LTS版"的发布节奏,LTS(长期支持)版本提供至少8年的官方支持,是企业级应用的首选。

版本 发布时间 类型 核心定位 支持周期
Java 8 2014-03 LTS 函数式编程革命,生态基石 免费支持至2026年
Java 11 2018-09 LTS 模块化成熟,云原生起步 免费支持至2027年
Java 17 2021-09 LTS 安全高效标杆,Spring Boot 3.0最低要求 免费支持至2029年
Java 21 2023-09 LTS 并发与语法革命,JDK8之后最重要版本 免费支持至2031年

1.2 从Java 8到21的核心演进脉络

  • Java 8-11:完成模块化革命(JPMS),引入var局部变量类型推断、新HTTP Client、ZGC/Shenandoah低延迟GC
  • Java 11-17:强化类型系统(密封类、记录类),完善模式匹配(instanceof),文本块转正,GC性能大幅提升
  • Java 17-21:并发编程范式革命(虚拟线程、结构化并发),语法表达力飞跃(模式匹配switch、序列集合),GC进一步优化

二、Java 8-20关键特性概览(JDK21基础)

2.1 语言特性演进

  • Java 8:Lambda表达式、Stream API、Optional、接口默认方法、新日期时间API
  • Java 10:var局部变量类型推断
  • Java 12-14:Switch表达式(预览→转正)
  • Java 13-15:文本块(Text Blocks,预览→转正)
  • Java 14-16:记录类(Records,预览→转正)、模式匹配instanceof(预览→转正)
  • Java 15-17:密封类(Sealed Classes,预览→转正)

2.2 运行时与性能优化

  • Java 9:G1 GC成为默认,引入ZGC/Shenandoah实验性GC
  • Java 11:ZGC/Shenandoah转为生产可用
  • Java 17:ZGC/Shenandoah性能大幅提升,支持更大堆内存
  • Java 18:UTF-8成为默认字符编码

三、JDK21 LTS四大核心特性深度解析

3.1 虚拟线程(Virtual Threads,JEP 444,正式特性)

3.1.1 传统平台线程的局限性
  • 1:1映射模型:每个Java线程直接对应一个操作系统内核线程
  • 资源消耗巨大:每个线程默认占用约1MB栈内存,创建数千线程即消耗数GB内存
  • 上下文切换昂贵:内核级线程切换需要保存/恢复大量寄存器状态
  • 阻塞即浪费:线程执行I/O操作时,整个内核线程被挂起,无法执行其他任务
3.1.2 虚拟线程的M:N调度模型

虚拟线程将线程管理从操作系统上移到JVM层,实现**大量虚拟线程(M)映射到少量平台线程(N)**的调度模型:

  • 载体线程(Carrier Thread):数量默认等于CPU核心数,由ForkJoinPool.commonPool管理
  • 虚拟线程:轻量级执行单元,初始栈空间仅4KB,可弹性扩展
  • 调度机制:虚拟线程阻塞时,JVM自动将其挂起,让出载体线程给其他就绪的虚拟线程
3.1.3 核心API与使用方式
java 复制代码
// 方式1:直接创建虚拟线程
Thread.startVirtualThread(() -> System.out.println("Hello Virtual Thread!"));

// 方式2:使用Thread.Builder(推荐,可配置线程属性)
Thread.Builder builder = Thread.ofVirtual()
        .name("worker-", 0)
        .uncaughtExceptionHandler((t, e) -> e.printStackTrace());
Thread vThread = builder.start(() -> doWork());

// 方式3:使用ExecutorService(最适合生产环境)
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 1_000_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1)); // 模拟I/O操作
            return i;
        });
    });
} // 自动关闭,等待所有任务完成
3.1.4 适用场景与最佳实践
  • ✅ 完美适配:I/O密集型任务(REST API调用、数据库访问、文件读写、消息队列消费)
  • ❌ 不适用:CPU密集型任务(视频解码、复杂数学计算)
  • 最佳实践
    • 不要池化虚拟线程(每个任务一个虚拟线程)
    • 避免在虚拟线程中使用ThreadLocal(改用作用域值Scoped Values)
    • 确保使用的框架和库已适配虚拟线程(Tomcat 10.1+、Spring Boot 3.2+)

3.2 模式匹配switch(Pattern Matching for switch,JEP 441,正式特性)

3.2.1 传统switch的局限性
  • 只能匹配常量值(int、enum、String等)
  • 不支持类型匹配
  • 空值会直接抛出NullPointerException
  • 复杂条件需要嵌套if-else
3.2.2 模式匹配switch的核心能力
  • 类型模式:直接在case标签中进行类型检查和变量绑定
  • 守卫模式(when子句):在类型匹配基础上添加额外条件
  • null处理:支持case null标签,优雅处理空值
  • 穷尽性检查:编译器自动检查switch是否覆盖所有可能情况
3.2.3 语法示例
java 复制代码
// 传统写法(冗长且易出错)
static String classifyOld(Object obj) {
    if (obj == null) {
        return "null";
    }
    if (obj instanceof Integer i) {
        if (i < 0) return "negative int";
        else if (i == 0) return "zero";
        else if (i % 2 == 0) return "even positive: " + i;
        else return "odd positive: " + i;
    }
    if (obj instanceof String s) {
        if (s.isBlank()) return "blank string";
        else return "string: " + s;
    }
    return "other";
}

// Java 21模式匹配写法(简洁优雅)
static String classifyNew(Object obj) {
    return switch (obj) {
        case null -> "null";
        case Integer i when i < 0 -> "negative int";
        case Integer i when i == 0 -> "zero";
        case Integer i when i % 2 == 0 -> "even positive: " + i;
        case Integer i -> "odd positive: " + i;
        case String s when s.isBlank() -> "blank string";
        case String s -> "string: " + s;
        default -> "other";
    };
}
3.2.4 与记录模式结合(JEP 440,正式特性)
java 复制代码
record Point(int x, int y) {}

static String describePoint(Object obj) {
    return switch (obj) {
        case Point(int x, int y) when x == 0 && y == 0 -> "原点";
        case Point(int x, int y) when x == y -> "对角线";
        case Point(int x, int y) -> "点(" + x + ", " + y + ")";
        default -> "不是点";
    };
}

3.3 结构化并发(Structured Concurrency,JEP 453,预览特性)

3.3.1 传统并发编程的问题
  • 任务生命周期不统一:父任务结束后,子任务可能继续运行成为"孤儿线程"
  • 错误处理复杂:一个子任务失败时,其他子任务仍在运行,浪费资源
  • 调试困难:线程dump中无法看到任务之间的父子关系
  • 代码可读性差:大量Future.get()和异常处理代码
3.3.2 结构化并发的核心思想

将多个相关的并发任务组织成父子任务结构,子任务的生命周期被严格限制在父任务的作用域内:

  • 父任务等待所有子任务完成
  • 任一子任务失败时,自动取消所有其他子任务
  • 线程dump中清晰显示任务的层次结构
3.3.3 核心API与使用方式
java 复制代码
// 场景1:所有任务必须成功(ShutdownOnFailure)
Order createOrder(Long userId, List<Long> productIds) throws ExecutionException, InterruptedException {
    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
        // 并行执行三个子任务
        var inventoryTask = scope.fork(() -> inventoryService.deductStock(productIds));
        var balanceTask = scope.fork(() -> paymentService.freezeBalance(userId, calculateTotal(productIds)));
        var logTask = scope.fork(() -> logService.recordOrderCreation(userId, productIds));
        
        // 等待所有任务完成,任一失败则取消其他任务
        scope.join().throwIfFailed();
        
        // 安全获取结果
        return new Order(
            inventoryTask.get(),
            balanceTask.get(),
            logTask.get()
        );
    }
}

// 场景2:最快结果优先(ShutdownOnSuccess)
String fetchDataFromMultipleSources(Long id) throws ExecutionException, InterruptedException {
    try (var scope = new StructuredTaskScope.ShutdownOnSuccess<String>()) {
        scope.fork(() -> cacheService.getData(id));
        scope.fork(() -> databaseService.getData(id));
        scope.fork(() -> externalApiService.getData(id));
        
        // 任一任务成功则取消其他任务
        return scope.join().result();
    }
}
3.3.4 与传统方案对比
能力 ExecutorService CompletableFuture StructuredTaskScope
自动等待所有任务
失败自动取消其他任务 ⚠️(需手动实现)
避免孤儿线程
清晰的任务层次结构
同步代码风格

3.4 序列集合(Sequenced Collections,JEP 431,正式特性)

3.4.1 传统集合框架的问题
  • 没有统一的接口表示"有明确顺序的集合"
  • 访问首尾元素的方法不一致:
    • List:get(0)、get(list.size()-1)
    • Deque:getFirst()、getLast()
    • LinkedHashSet:需要通过迭代器访问
    • LinkedHashMap:需要通过entrySet().iterator()访问
  • 反转集合需要创建新集合,效率低
3.4.2 序列集合接口体系

Java 21引入了三个新接口,统一了有序集合的操作:

复制代码
Collection
└── SequencedCollection
    ├── List
    ├── Deque
    └── SequencedSet
        └── SortedSet
            └── NavigableSet

Map
└── SequencedMap
    └── SortedMap
        └── NavigableMap
3.4.3 核心方法

SequencedCollection接口

  • E getFirst():获取第一个元素
  • E getLast():获取最后一个元素
  • void addFirst(E e):在头部添加元素
  • void addLast(E e):在尾部添加元素
  • E removeFirst():删除并返回第一个元素
  • E removeLast():删除并返回最后一个元素
  • SequencedCollection<E> reversed():返回反转视图(不复制元素)

SequencedMap接口

  • Map.Entry<K,V> firstEntry():获取第一个条目
  • Map.Entry<K,V> lastEntry():获取最后一个条目
  • Map.Entry<K,V> pollFirstEntry():删除并返回第一个条目
  • Map.Entry<K,V> pollLastEntry():删除并返回最后一个条目
  • V putFirst(K key, V value):在头部添加条目
  • V putLast(K key, V value):在尾部添加条目
  • SequencedMap<K,V> reversed():返回反转视图
3.4.4 使用示例
java 复制代码
// 统一访问有序集合的首尾元素
void processFirstAndLast(SequencedCollection<String> items) {
    String first = items.getFirst();
    String last = items.getLast();
    System.out.println("First: " + first + ", Last: " + last);
}

// 反转集合(视图,高效)
List<String> list = new ArrayList<>(List.of("a", "b", "c"));
SequencedCollection<String> reversedList = list.reversed();
System.out.println(reversedList); // [c, b, a]

// 修改反转视图会影响原集合
reversedList.addFirst("d");
System.out.println(list); // [a, b, c, d]

// SequencedMap示例
SequencedMap<String, Integer> map = new LinkedHashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);

System.out.println(map.firstEntry()); // a=1
System.out.println(map.lastEntry()); // c=3
System.out.println(map.reversed()); // {c=3, b=2, a=1}

四、JDK21其他重要特性

4.1 分代ZGC(Generational ZGC,JEP 439,正式特性)

  • 将堆分为新生代和老年代,针对不同代的对象采用不同的收集策略
  • 年轻代对象存活率低,收集更频繁;老年代对象存活率高,收集更少
  • 相比JDK17的ZGC,吞吐量提升约25%,暂停时间仍保持在亚毫秒级
  • 启用参数:java -XX:+UseZGC -XX:+ZGenerational -jar app.jar(JDK21默认启用)

4.2 字符串模板(String Templates,JEP 430,预览特性)

  • 提供更简洁、安全的字符串构建方式
  • 支持在字符串字面量中嵌入表达式
  • 可自定义模板处理器,防止SQL注入等安全问题
java 复制代码
String name = "张三";
int age = 25;
String message = STR."姓名: \{name}, 年龄: \{age}";

// 安全SQL查询(示例)
String query = SQL."SELECT * FROM users WHERE name = \{name}";

4.3 未命名模式和变量(Unnamed Patterns and Variables,JEP 443,预览特性)

  • 使用下划线_表示未使用的变量或模式
  • 提高代码可读性,消除不必要的变量声明
java 复制代码
// 未命名变量
try (var _ = new Timer()) {
    // 不需要引用Timer对象
}

// 未命名模式
if (obj instanceof Point(int x, _)) {
    // 只关心x坐标
    System.out.println("x: " + x);
}

4.4 作用域值(Scoped Values,JEP 446,预览特性)

  • 虚拟线程环境下ThreadLocal的替代方案
  • 更轻量、更安全,支持父子线程间的不可变数据传递
  • 避免ThreadLocal在虚拟线程中的内存泄漏问题

五、迁移建议与最佳实践

5.1 分阶段迁移策略

  1. 阶段1:环境准备与依赖分析

    • 使用jdeprscan工具分析项目中使用的废弃API
    • 升级关键依赖:Spring Boot 3.2+、Tomcat 10.1+、Hibernate 6.4+、Lombok 1.18.30+
    • 配置IDE支持Java 21
  2. 阶段2:从Java 8升级到Java 17

    • 处理javax→jakarta包名变更
    • 解决模块化系统带来的反射访问限制
    • 替换已移除的API(如Thread.stop()
  3. 阶段3:从Java 17升级到Java 21

    • 启用虚拟线程(Spring Boot:spring.threads.virtual.enabled=true
    • 逐步采用新语法特性(模式匹配switch、序列集合)
    • 启用分代ZGC
  4. 阶段4:性能优化与特性深度应用

    • 重构异步代码为结构化并发
    • 替换ThreadLocal为作用域值
    • 优化GC参数

5.2 常见兼容性问题与解决方案

问题 解决方案
非法反射访问警告 升级依赖库至支持JPMS的版本,或临时添加--add-opens参数
UTF-8默认编码 移除手动指定编码的冗余代码,确保文件编码为UTF-8
废弃API 使用jdeprscan识别并替换为新API
虚拟线程兼容性 避免在虚拟线程中使用池化技术和ThreadLocal

5.3 生产环境最佳实践

  • 新项目:直接使用Java 21 + Spring Boot 3.2+
  • 老项目:先升级到Java 17稳定运行后,再考虑升级到Java 21
  • 并发场景:I/O密集型任务全面使用虚拟线程,CPU密集型任务继续使用传统线程池
  • 代码风格:逐步采用新语法特性,提高代码可读性和可维护性

六、总结与未来展望

Java 21是自Java 8以来最重要的LTS版本,它通过虚拟线程 彻底改变了Java并发编程的范式,通过模式匹配switch序列集合 大幅提升了语言的表达力,通过结构化并发简化了多任务协作的复杂性。

未来Java将继续沿着"提高生产力、简化并发编程、提升性能"的方向演进:

  • Java 22-25将进一步完善虚拟线程生态
  • 字符串模板、结构化并发等预览特性将逐步转正
  • 继续优化GC性能,降低延迟
  • 引入更多现代语言特性,如值类型、泛型改进等

对于企业和开发者来说,升级到Java 21不仅能获得显著的性能提升和开发效率改善,还能为未来5-8年的技术发展奠定坚实基础。


Java 8-21新特性面试背诵版(JDK21 LTS核心考点)

适用场景 :Java后端面试、技术评审、快速复习
核心原则 :只保留面试官最常问的定义、原理、优缺点、使用场景、代码示例,所有考点均为高频必背


一、Java版本演进与LTS战略(面试必问基础)

1.1 LTS版本时间线与核心定位(必背表格)

版本 发布时间 核心定位 企业应用现状
Java 8 2014-03 函数式编程革命,生态基石 存量项目最多,即将停止免费支持
Java 11 2018-09 模块化成熟,云原生起步 目前企业主流版本
Java 17 2021-09 安全高效标杆,Spring Boot 3.0最低要求 快速普及中
Java 21 2023-09 并发与语法革命,JDK8之后最重要版本 未来5-8年企业标准

1.2 核心演进脉络(一句话总结)

  • Java 8-11:完成模块化(JPMS),引入var、新HTTP Client、ZGC/Shenandoah低延迟GC
  • Java 11-17:强化类型系统(记录类、密封类),完善模式匹配(instanceof),文本块转正
  • Java 17-21:并发范式革命(虚拟线程、结构化并发),语法表达力飞跃(模式匹配switch、序列集合)

二、Java 8-20高频考点速记(每个版本1个核心特性)

  1. Java 8:Lambda表达式、Stream API、Optional、新日期时间API(面试必问)
  2. Java 10:var局部变量类型推断(只能用于局部变量)
  3. Java 14:Switch表达式(箭头语法,返回值,无fall-through)
  4. Java 15 :文本块(""",保留格式,自动处理换行)
  5. Java 16:记录类(Records,不可变数据载体,自动生成equals/hashCode/toString)
  6. Java 16 :模式匹配instanceof(if (obj instanceof String s),自动类型转换)
  7. Java 17 :密封类(Sealed Classes,限制类的继承层次,permits关键字)

三、JDK21四大核心特性(面试重中之重,占比80%)

3.1 虚拟线程(Virtual Threads,JEP 444,正式)

核心定义:JVM层面实现的轻量级线程,采用M:N调度模型,解决传统平台线程资源消耗大、阻塞即浪费的问题。

传统平台线程痛点(必背):

  • 1:1映射内核线程,每个线程默认占用1MB栈内存
  • 上下文切换昂贵(内核态切换)
  • I/O阻塞时整个内核线程被挂起,资源利用率低
  • 单机最多创建数千个线程

核心原理(必背):

  • M:N调度:大量虚拟线程(M)映射到少量平台线程(N)
  • 载体线程:数量默认等于CPU核心数,由ForkJoinPool.commonPool管理
  • 挂载/卸载机制:虚拟线程阻塞时,JVM自动将其从载体线程卸载,让出资源给其他虚拟线程
  • 栈内存:初始仅4KB,可弹性扩展,支持百万级并发

核心API(3种创建方式)

java 复制代码
// 1. 直接创建
Thread.startVirtualThread(() -> doIO());

// 2. Thread.Builder(推荐)
Thread vThread = Thread.ofVirtual().name("worker-", 0).start(() -> doIO());

// 3. ExecutorService(生产环境首选,自动关闭)
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    for (int i=0; i<1000000; i++) {
        executor.submit(() -> doIO());
    }
}

适用场景(必背):

  • I/O密集型任务:REST调用、数据库访问、文件读写、消息消费
  • CPU密集型任务:视频解码、复杂数学计算(不会阻塞,无法发挥优势)

面试高频坑点(必背):

  1. 绝对不要池化虚拟线程:每个任务一个虚拟线程,池化会失去轻量级优势
  2. 避免使用ThreadLocal:改用作用域值(Scoped Values),防止内存泄漏
  3. 阻塞操作必须由JVM感知Thread.sleep()Socket.connect()等已适配,LockSupport.park()需手动处理
  4. 载体线程不会阻塞:虚拟线程阻塞时,载体线程会执行其他虚拟线程
  5. 同步块会pin载体线程 :尽量使用java.util.concurrent.locks替代synchronized

3.2 模式匹配switch(Pattern Matching for switch,JEP 441,正式)

核心定义:扩展switch语句/表达式的能力,支持类型匹配、守卫条件、null处理和穷尽性检查,大幅简化多条件分支代码。

传统switch痛点

  • 只能匹配常量值(int、enum、String)
  • 不支持类型匹配,需要嵌套if-else
  • 空值直接抛NullPointerException
  • 无fall-through检查,易出错

核心能力(必背):

  1. 类型模式:直接在case中进行类型检查和变量绑定
  2. 守卫模式when子句添加额外条件
  3. null处理 :支持case null标签
  4. 穷尽性检查:编译器自动检查是否覆盖所有可能情况(密封类、枚举)

核心语法示例(对比传统写法)

java 复制代码
// Java 21写法(必背)
static String classify(Object obj) {
    return switch (obj) {
        case null -> "null"; // 优雅处理空值
        case Integer i when i < 0 -> "negative"; // 类型+守卫
        case Integer i -> "positive";
        case String s when s.isBlank() -> "blank";
        case String s -> "string: " + s;
        default -> "other";
    };
}

与记录模式结合(JEP 440,正式)

java 复制代码
record Point(int x, int y) {}

static String describe(Point p) {
    return switch (p) {
        case Point(int x, int y) when x == 0 && y == 0 -> "原点";
        case Point(int x, int y) when x == y -> "对角线";
        case Point(int x, int y) -> "(" + x + "," + y + ")";
    };
}

面试高频坑点

  1. 模式匹配switch没有fall-through(箭头语法)
  2. 类型模式必须是可转换的,否则编译错误
  3. 守卫条件when必须是布尔表达式,不能有副作用
  4. 对于密封类,编译器会自动检查穷尽性,不需要default

3.3 结构化并发(Structured Concurrency,JEP 453,预览)

核心定义:将多个相关的并发任务组织成父子任务结构,子任务的生命周期严格限制在父任务的作用域内,解决传统并发的孤儿线程、错误处理复杂、调试困难等问题。

传统并发痛点(必背):

  • 父任务结束后,子任务可能继续运行成为"孤儿线程"
  • 一个子任务失败时,其他子任务仍在运行,浪费资源
  • 线程dump中无法看到任务的父子关系
  • 代码可读性差,大量Future.get()和异常处理

核心思想(必背):

并发任务的生命周期应该与代码的结构层次相对应,就像同步代码中的函数调用一样。

两种核心策略(必背)

  1. ShutdownOnFailure:所有任务必须成功,任一失败则取消所有其他任务
  2. ShutdownOnSuccess:任一任务成功则取消所有其他任务,返回最快结果

核心代码示例

java 复制代码
// ShutdownOnFailure(必背)
Order createOrder(Long userId, List<Long> productIds) throws Exception {
    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
        var inventoryTask = scope.fork(() -> inventoryService.deduct(productIds));
        var balanceTask = scope.fork(() -> paymentService.freeze(userId, calculateTotal(productIds)));
        
        scope.join().throwIfFailed(); // 等待所有任务,失败则抛异常
        
        return new Order(inventoryTask.get(), balanceTask.get());
    }
}

// ShutdownOnSuccess
String fetchFastest(Long id) throws Exception {
    try (var scope = new StructuredTaskScope.ShutdownOnSuccess<String>()) {
        scope.fork(() -> cache.get(id));
        scope.fork(() -> db.get(id));
        scope.fork(() -> api.get(id));
        
        return scope.join().result(); // 返回第一个成功的结果
    }
}

与CompletableFuture对比(必背表格)

能力 CompletableFuture StructuredTaskScope
自动等待所有任务
失败自动取消其他任务 ❌(需手动实现)
避免孤儿线程
清晰的任务层次结构
同步代码风格

面试高频坑点

  1. 结构化并发必须在try-with-resources中使用,确保scope自动关闭
  2. fork()方法立即提交任务 ,不是在join()时才执行
  3. 子任务抛出的异常会被包装在ExecutionException
  4. 目前是预览特性,需要添加--enable-preview参数启用

3.4 序列集合(Sequenced Collections,JEP 431,正式)

核心定义:引入统一的接口体系表示"有明确顺序的集合",解决传统集合框架中有序集合操作不一致、访问首尾元素繁琐的问题。

传统集合痛点(必背):

  • 没有统一接口表示有序集合
  • 访问首尾元素方法不一致:
    • List:get(0)get(size()-1)
    • Deque:getFirst()getLast()
    • LinkedHashSet/LinkedHashMap:需要通过迭代器访问
  • 反转集合需要创建新集合,效率低

接口体系(必背树形结构)

复制代码
Collection
└── SequencedCollection
    ├── List
    ├── Deque
    └── SequencedSet
        └── SortedSet
            └── NavigableSet

Map
└── SequencedMap
    └── SortedMap
        └── NavigableMap

核心方法(必背)

  • SequencedCollection
    getFirst()getLast()addFirst()addLast()removeFirst()removeLast()reversed()(返回视图,不复制元素)
  • SequencedMap
    firstEntry()lastEntry()pollFirstEntry()pollLastEntry()putFirst()putLast()reversed()

核心代码示例

java 复制代码
// 统一访问所有有序集合的首尾元素
void process(SequencedCollection<String> items) {
    String first = items.getFirst();
    String last = items.getLast();
}

// 高效反转(视图,O(1)时间复杂度)
List<String> list = new ArrayList<>(List.of("a", "b", "c"));
SequencedCollection<String> reversed = list.reversed();
System.out.println(reversed); // [c, b, a]

// 修改视图会影响原集合
reversed.addFirst("d");
System.out.println(list); // [a, b, c, d]

面试高频坑点

  1. reversed()返回的是视图,不是新集合,修改会影响原集合
  2. addFirst()对于ArrayList是O(n)时间复杂度(需要移动元素)
  3. putFirst()对于LinkedHashMap是O(1),对于TreeMap是O(log n)
  4. 不可变集合的reversed()视图也是不可变的

四、JDK21其他高频考点

  1. 分代ZGC(JEP 439,正式)

    • 将堆分为新生代和老年代,吞吐量提升约25%
    • 暂停时间仍保持在亚毫秒级(<1ms)
    • JDK21默认启用,参数:-XX:+UseZGC -XX:+ZGenerational
  2. 作用域值(Scoped Values,JEP 446,预览)

    • 虚拟线程环境下ThreadLocal的替代方案
    • 更轻量、更安全,支持父子线程间不可变数据传递
    • 避免ThreadLocal在虚拟线程中的内存泄漏问题
  3. 未命名模式和变量(JEP 443,预览)

    • 使用下划线_表示未使用的变量或模式
    • 示例:try (var _ = new Timer()) { ... }case Point(int x, _) -> ...
  4. 字符串模板(JEP 430,预览)

    • 语法:STR."姓名: \{name}, 年龄: \{age}"
    • 支持自定义模板处理器,可防止SQL注入

五、迁移与最佳实践高频考点

5.1 分阶段迁移策略(必背)

  1. 环境准备 :使用jdeprscan分析废弃API,升级关键依赖(Spring Boot 3.2+、Tomcat 10.1+)
  2. 升级到Java 17:处理javax→jakarta包名变更,解决反射访问限制
  3. 升级到Java 21 :启用虚拟线程(Spring Boot:spring.threads.virtual.enabled=true
  4. 深度应用:逐步采用新语法特性,重构异步代码为结构化并发

5.2 虚拟线程最佳实践(必背)

  • 每个任务一个虚拟线程,不要池化
  • I/O密集型任务全面使用,CPU密集型任务继续使用传统线程池
  • 避免在虚拟线程中使用synchronized同步块
  • 替换ThreadLocal为作用域值
  • 确保使用的框架和库已适配虚拟线程

六、面试高频问答TOP10(直接背诵)

  1. Q:虚拟线程和平台线程的区别是什么?

    A:平台线程是1:1映射内核线程,资源消耗大,上下文切换昂贵;虚拟线程是JVM实现的M:N调度,轻量级(初始4KB栈),支持百万级并发,阻塞时自动让出载体线程。

  2. Q:为什么不能池化虚拟线程?

    A:虚拟线程的创建成本极低(几乎和创建对象一样),池化会引入不必要的开销和复杂度,失去轻量级优势。每个任务一个虚拟线程是最佳实践。

  3. Q:模式匹配switch相比传统switch有哪些改进?

    A:支持类型匹配、守卫条件、null处理和穷尽性检查,没有fall-through,代码更简洁易读。

  4. Q:结构化并发解决了什么问题?

    A:解决了传统并发中的孤儿线程、错误处理复杂、调试困难等问题,将并发任务的生命周期与代码结构对应起来。

  5. Q:序列集合解决了什么问题?

    A:统一了有序集合的操作接口,简化了首尾元素的访问和反转操作,提高了代码的一致性和可读性。

  6. Q:分代ZGC相比非分代ZGC有什么优势?

    A:针对不同代的对象采用不同的收集策略,年轻代收集更频繁,老年代收集更少,吞吐量提升约25%,同时保持亚毫秒级暂停时间。

  7. Q:作用域值和ThreadLocal有什么区别?

    A:作用域值是不可变的,支持父子线程间传递,更轻量,不会在虚拟线程中造成内存泄漏;ThreadLocal是可变的,每个线程有自己的副本,容易泄漏。

  8. Q:Java 21相比Java 17有哪些最重要的改进?

    A:虚拟线程、模式匹配switch、结构化并发、序列集合、分代ZGC。

  9. Q:虚拟线程适用于什么场景?不适用于什么场景?

    A:适用于I/O密集型任务(REST调用、数据库访问);不适用于CPU密集型任务(视频解码、复杂计算)。

  10. Q:从Java 8升级到Java 21需要注意哪些问题?

    A:处理javax→jakarta包名变更,解决非法反射访问警告,替换已移除的API,升级依赖库,逐步启用新特性。


Java 8-21新特性一页纸速记版(考前突击专用)

适用场景 :面试前10分钟快速过一遍,只记数字、关键词、必背结论
核心原则:所有内容均为面试官最常问的考点,无任何冗余


一、LTS版本速记表(必背)

版本 发布时间 核心标签 企业地位
Java 8 2014 函数式 存量最多
Java 11 2018 模块化 目前主流
Java 17 2021 安全 Spring Boot 3.0+
Java 21 2023 并发革命 未来标准

演进脉络:8(函数式)→11(模块化)→17(类型系统)→21(并发+语法)


二、Java 8-20核心特性速记(每个版本1个词)

  • Java 8:Lambda、Stream、Optional
  • Java 10:var(局部变量)
  • Java 14:Switch表达式(无fall-through)
  • Java 15:文本块("""
  • Java 16:记录类(Records,不可变)、模式匹配instanceof
  • Java 17:密封类(Sealed,限制继承)

三、JDK21四大核心特性(重中之重)

1. 虚拟线程(Virtual Threads)✅ 必考

  • 定义:JVM实现的轻量级线程,M:N调度
  • 核心数字:初始栈4KB,支持百万级并发
  • 载体线程:默认=CPU核心数,ForkJoinPool管理
  • 适用:✅ I/O密集型(DB、API、文件)
  • 禁忌:❌ CPU密集型、❌ 池化、❌ ThreadLocal
  • 坑点:synchronized会pin载体线程

2. 模式匹配switch ✅ 必考

  • 定义:扩展switch支持类型匹配和条件
  • 核心能力:类型模式+when守卫+null处理+穷尽检查
  • 语法case Integer i when i<0 -> "negative"
  • 结合 :记录模式(case Point(int x, int y)
  • 特点:无fall-through

3. 结构化并发(预览)

  • 定义:父子任务生命周期绑定
  • 核心思想:并发结构=代码结构
  • 两种策略
    • ShutdownOnFailure:全成功,失败则全取消
    • ShutdownOnSuccess:取最快,成功则全取消
  • 解决:孤儿线程、错误处理复杂
  • 使用:必须在try-with-resources中

4. 序列集合(Sequenced Collections)

  • 定义:统一有序集合操作接口
  • 接口体系:SequencedCollection/Set/Map
  • 核心方法:getFirst()、getLast()、reversed()(视图)
  • 解决:首尾元素访问不一致、反转低效
  • 坑点:reversed()是视图,修改影响原集合

四、JDK21其他高频考点

  1. 分代ZGC:默认启用,吞吐量+25%,暂停<1ms
  2. 作用域值:虚拟线程替代ThreadLocal,不可变
  3. 未命名变量_表示未使用
  4. 字符串模板STR."姓名: \{name}"(预览)

五、迁移最佳实践速记

  1. 先升级到Java 17(处理javax→jakarta)
  2. 再升级到Java 21
  3. Spring Boot 3.2+:spring.threads.virtual.enabled=true
  4. 逐步替换:I/O密集型→虚拟线程,异步→结构化并发

六、面试TOP5必背答案(直接说)

  1. 虚拟线程vs平台线程:1:1 vs M:N,1MB vs 4KB,千级 vs 百万级
  2. 为什么不能池化虚拟线程:创建成本极低,池化失去优势
  3. 结构化并发解决什么问题:孤儿线程、错误处理复杂
  4. 序列集合解决什么问题:统一有序集合操作
  5. Java 21最重要改进:虚拟线程(并发范式革命)

考前最后看一眼:虚拟线程的M:N调度、4KB栈、百万级并发、I/O密集型适用、禁池化。这5个点90%的面试都会问到。

相关推荐
张登杰踩4 小时前
DINOv2 with Registers 系列模型详解:Giant 版本规格、Register Token 机制与使用指南
python·numpy
June`4 小时前
多线程redis下如何解决aof重写和rdb持久化的数据一致性问题
数据库·redis·缓存
木心术14 小时前
Windows系统下MySQL与AI工具集成方案:数据存储与调用实践
人工智能·windows·mysql
隐于花海,等待花开4 小时前
9. Python 文件与输入输出 深度解析
python
二宝哥4 小时前
离线安装maven
java·数据库·maven
SZLSDH5 小时前
场景适配论 | 数字孪生IOC建设中渲染技术与智能体能力的协同逻辑
前端·数据库·ai·数字孪生·数据可视化·智能体
这个DBA有点耶5 小时前
SQL改写实战:子查询、CTE、窗口函数性能对比
数据库·mysql·性能优化
@我漫长的孤独流浪5 小时前
数据库完整性约束全解析:从理论到实践
数据库
日月云棠5 小时前
6 高级配置:Spring Boot整合、泛化调用与配置指南
java·后端