来自网络,供学习,侵删 某猪 某皮
先完成再完美
1.jdk8和jdk17有什么区别,有哪些更新
- 性能与底层 :
- 垃圾回收器 :JDK 8 默认 Parallel GC,JDK 17 默认 G1 GC ,并引入了 ZGC(低延迟,亚毫秒级暂停)。
- 启动速度:JDK 17 优化了类加载和 JIT 编译,启动速度更快,内存占用更低。
2.stream流场景题,List里面有person类,person里面有name,age,stream流把List里面变成map,其中键为name,值为person;
java8新特性
Map<String, Person> personMap = personList.stream() .collect(Collectors.toMap(Person::getName, person -> person)); // 或者使用方法引用 // .collect(Collectors.toMap(Person::getName, Function.identity()));
3.jdk17为了适应什么框架
JDK 17 的演进很大程度上是为了适应 云原生 (Cloud Native) 和 微服务 架构,特别是为了配合 Spring Boot 3.x 和 Spring Framework 6 的升级。
- Spring Boot 3.0+ 强制要求最低 Java 版本为 17。
- GraalVM 原生镜像:JDK 17 的改进(如分层编译、更强的封装)使得 Java 应用更容易被编译成原生镜像,实现秒级启动和极低内存占用,这对 Serverless 和容器化部署至关重要。
4.单例模式,策略模式和工厂模式解释下
单例模式的话,懒汉,饿汉,静态内部类,双重锁校验
-
工厂模式 (Factory Pattern):
- 定义 :1定义一个创建对象的接口,但让2子类决定实例化哪一个类。或者简单理解为一个"生产对象的车间"。3.调用工厂方法就能实例化
- 作用:解耦对象的创建和使用。调用方不需要知道具体类的类名,只需要知道工厂和接口。
- 例子 :
Calendar.getInstance()就是一个简单的工厂方法。
-
策略模式 (Strategy Pattern):
- 定义:定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。
- 作用 :消除大量的
if-else或switch判断。 - 例子 :电商订单的支付方式(支付宝、微信、银联)。定义一个
PaymentStrategy接口,不同支付方式实现该接口。根据用户选择,注入不同的策略实现类。通常配合工厂模式或 Map 容器来根据类型获取对应的策略。
5. Java 回收器了解吗?G1 和 ZGC 回收器
VM 垃圾回收器的核心目标是平衡 吞吐量 (Throughput) 和 延迟 (Latency/Pause Time)。
- G1 (Garbage-First) :
- 特点:JDK 9+ 的默认回收器。将堆内存划分为多个独立的区域(Region),不再物理隔离新生代和老年代。
- 优势:可预测的停顿时间模型。用户可以指定期望的停顿时间(如 200ms),G1 会尽力达成。适合大内存(6GB+)、多核 CPU 的服务器端应用。
- ZGC (Z Garbage Collector) :
- 特点 :JDK 15+ 正式商用。基于 读屏障 和 染色指针 技术。
- 优势 :亚毫秒级的停顿时间(通常 < 1ms),且停顿时间不随堆内存大小增长而增长(支持 TB 级堆内存)。
- 适用:对延迟极其敏感的系统,如高频交易、实时大数据处理。
6场景题:100w订单量问题进行表设计和库设计,订单分布式ID怎么设计,商家怎么通过你设计的表形成商家的订单列表,分库怎么查找
- 分库分表 :100w 数据量在 MySQL 单表中其实不算大(通常 500w-1000w 是分界线)。如果预估会增长到千万级,需提前分表。
- 策略 :通常按
user_id取模分库分表,保证同一个用户的订单在同一个库/表中,方便查询。
- 策略 :通常按
- 表结构 :
-
id(bigint, 主键) -
order_no(varchar, 业务订单号,唯一索引) -
user_id(bigint, 分片键) -
merchant_id(bigint, 商家ID) -
amount(decimal) -
status(tinyint) -
create_time(datetime) -
2. 分布式 ID 设计
-
雪花算法 (Snowflake) :最常用。生成 64 位 Long 型 ID(时间戳 + 机器 ID + 序列号),趋势递增,性能好,不依赖数据库。
-
数据库号段模式:美团 Leaf 等方案,依赖数据库生成号段,可靠性高。
-
3. 商家订单列表与分库查找
-
痛点 :订单表按
user_id分片,但商家需要按merchant_id查询。这属于"非分片键查询"。 -
解决方案 :
- 方案 A (异构索引表) :建立一张专门的商家订单表(
merchant_order),按merchant_id分片,异步同步数据。 - 方案 B (Elasticsearch):将订单数据同步到 ES,商家查询走 ES,详情查询走 MySQL。
- 方案 C (广播表/冗余字段) :如果商家数量少,可以在订单表中冗余
merchant_id,利用数据库中间件(如 ShardingSphere)的广播表功能或全表扫描(不推荐,性能差)。
- 方案 A (异构索引表) :建立一张专门的商家订单表(
-
7总体架构,传统三层架构和ddd架构有什么区别
-
传统三层架构 (MVC/Service/Dao):
- 核心 :贫血模型。实体类(Entity)只有 Getter/Setter,业务逻辑全部堆积在 Service 层(Transaction Script 模式)。
- 缺点:随着业务复杂,Service 类会变得极其臃肿,难以维护,且容易违反单一职责原则。
- 适用:简单的 CRUD 管理系统。
-
DDD (领域驱动设计) :
- 核心 :充血模型 。业务逻辑下沉到领域对象(Entity/Value Object)中,Service 层只负责协调。
- 结构:通常分为接口层、应用层、领域层、基础设施层(六边形架构/整洁架构)。
- 优点:代码结构与业务语言统一(通用语言),高内聚低耦合,适合复杂业务系统(如电商、金融核心)
8.项目里kafka里面有哪些注意点
- 消息丢失 :
- 生产者:开启
acks=all,重试次数设为最大值。 - Broker:
min.insync.replicas > 1。 - 消费者:关闭自动提交 offset,业务处理成功后再手动提交。
- 生产者:开启
- 消息重复消费 :
- Kafka 只能保证"至少一次"。消费者必须实现 幂等性(如利用数据库唯一键、Redis 防重表)。
- 消息积压 :
- 排查消费者处理逻辑是否过慢。
- 临时扩容:增加 Partition 数量,增加消费者实例。
- 顺序消息 :
- Kafka 只保证 Partition 内的顺序。如果需要全局顺序,只能用一个 Partition(性能差);通常只需要保证"同一订单/同一 Key"的顺序,发送时指定 Key 即可。
9.JMM了解吗
JMM 定义了 Java 虚拟机与计算机内存(主内存)之间的交互规则。
- 核心概念 :
- 主内存:所有变量存储的地方。
- 工作内存:每个线程的私有内存,保存了该线程使用到的变量的主内存副本。
- 三大特性 :
- 原子性 :操作不可中断(如
synchronized)。 - 可见性 :一个线程修改了变量,其他线程立即可见(如
volatile)。 - 有序性 :禁止指令重排序(如
volatile)。
- 原子性 :操作不可中断(如
- Happens-Before 原则:判断数据是否存在竞争、线程是否安全的依据。
10.垃圾回收了解吗
- 判断对象存活 :引用计数法(已淘汰)、可达性分析算法(GC Roots)。
- 分代收集理论 :
- 新生代 :对象朝生夕死,使用 复制算法(Eden, Survivor)。
- 老年代 :对象存活率高,使用 标记-整理 或 标记-清除 算法。
- STW (Stop-The-World):GC 发生时,用户线程暂停。优化的核心就是减少 STW 时间。
11.mysql有一个表,abc三列,b是索引,a是主键,where b =1,经过几次IO
- 查找索引 b :InnoDB 的二级索引(辅助索引)叶子节点存储的是 索引列的值 (b) 和 主键值 (a) 。
- 首先在
b的 B+ 树中找到b=1的节点。假设树高为 h1(通常 2-3 层),需要 h1 次 IO。
- 首先在
- 回表 :因为查询需要所有列(或者非覆盖索引),拿到主键
a后,需要回到 聚簇索引(主键索引) 树中查找完整的行数据。- 在主键
a的 B+ 树中查找,假设树高为 h2(通常 2-3 层),需要 h2 次 IO。
- 在主键
12.分布式锁了解吗,redis怎么实现分布式锁
- 基本实现 :
SET key value NX PX 30000(Set If Not Exists + 过期时间)。- 利用 Redis 单线程特性保证原子性。
- 关键点 :
- 超时时间:防止死锁。
- Value 值 :通常设为 UUID+ThreadID,用于释放锁时校验(只能删除自己的锁,防止误删别人的锁)。
- 原子删除:使用 Lua 脚本判断 Value 并删除。
- 进阶 (Redisson) :
- 看门狗机制:如果业务没执行完,后台线程自动给锁"续期"。
- 红锁:在多个 Redis 主节点上尝试加锁,提高可靠性。
13JUC并发编程中用到哪些数据结构
- ConcurrentHashMap :
- JDK 8:Node 数组 + 链表 + 红黑树。使用 CAS +
synchronized保证线程安全,锁粒度更细(只锁链表头节点)。
- JDK 8:Node 数组 + 链表 + 红黑树。使用 CAS +
- ThreadLocal :
- 线程本地变量,每个线程内部维护一个
ThreadLocalMap,实现线程隔离。
- 线程本地变量,每个线程内部维护一个
- BlockingQueue (阻塞队列) :
ArrayBlockingQueue、LinkedBlockingQueue。用于线程池任务队列,生产消费解耦。
- AQS (AbstractQueuedSynchronizer) :
- 底层核心,维护了一个 CLH 双向队列 来管理等待锁的线程。
ReentrantLock、CountDownLatch都基于它。
- 底层核心,维护了一个 CLH 双向队列 来管理等待锁的线程。
14.有JVM调优经验吗
- 监控 :使用 Prometheus + Grafana 监控 JVM 的堆内存使用率和 GC 频率。
- 排查 OOM :当发生 OOM 时,通过启动参数
-XX:+HeapDumpOnOutOfMemoryError生成 Dump 文件,使用 MAT 或 JProfiler 分析大对象和内存泄漏点(比如静态集合类无限增长)。 - 排查 CPU 飙高 :使用 top
-H -p <pid>找到占用 CPU 高的线程 ID,转换为 16 进制,再用jstack查看堆栈,定位是死循环还是频繁 GC 导致的。 - 参数调整 :根据业务场景调整堆内存大小(-Xmx, -Xms)以及选择合适的垃圾回收器(如将默认的 Parallel GC 换成 G1 以减少停顿)。"