EXPLORE · 循迹而来

Java

FOLLOW YOUR CURIOSITY

把同一个话题,读得更深。

这个话题下有 88 篇手记。

Java 7 和 8 的 HashMap 与 ConcurrentHashMap 源码解析

1392 阅读

文章系统地解析了 Java7/8 中 HashMap 与 ConcurrentHashMap 的实现细节。HashMap 采用数组+单向链表结构,容量始终为 2ⁿ,使用 loadFactor 与 threshold 控制扩容;put 时先计算 hash、定位桶、遍历链表去重,必要时双倍扩容并重新分配节点;get 通过相同的 hash 与 index 直接查找链表。ConcurrentHashMap 在此基础上引入 Segment(分段锁)实现并发,默认 16 段,每段内部类似 HashMap 并保持线程安全,初始化时将整体容量划分给各段,put 通过高位 hash 确定段并在对应 Segment 加锁后操作。全文重点说明了数组初始化、索引计算、节点插入、扩容机制以及并发控制的实现原理。

JVM对象创建与内存分配机制

1676 阅读

JVM在执行new指令时首先检查类是否已加载、解析、初始化,然后在堆中为对象分配内存,采用“指针碰撞”或“空闲列表”方式,并通过CAS或TLAB解决并发冲突。分配后进行零值填充,设置对象头(包含hash、年龄、锁状态、类指针等),最后执行构造函数完成属性赋值。对象大小受对象头、实例字段和8字节对齐填充影响,默认开启指针压缩(UseCompressedOops/UseCompressedClassPointers)以降低内存占用并支持最高32 GB堆。JVM通过逃逸分析和标量替换可将不逃逸对象分配到栈上,减轻GC压力。

JVM类加载机制

1579 阅读

JVM在执行 main 方法时先通过类加载器把主类加载到方法区,加载过程依次为加载、验证、准备、解析、初始化。加载阶段在内存生成对应的 Class 对象;验证检查字节码合法性;准备为静态字段分配默认值;解析把符号引用转为直接引用;初始化执行静态代码块并赋予真实值。JVM 提供引导、扩展、应用和自定义四种加载器,启动时由 Launcher 创建 ExtClassLoader 与 AppClassLoader。类加载遵循双亲委派机制:先交给父加载器(最终到引导加载器)尝试加载,若失败再由当前加载器自行查找。示例代码展示了按需加载、静态块打印以及各加载器的加载路径,说明了类加载的延迟性和层次结构。

Java 21 的新特性一览

548 阅读

Java 21(2023 9月发布)是继 17 后的下一个 LTS,正式推出 15 项 JEP。核心亮点包括:虚拟线程(JEP 444)实现数百万轻量线程、资源占用极低,配合结构化并发(JEP 453)提供任务范围管理与异常传播;序列集合(JEP 431)扩展 List、Map 的顺序操作;记录模式与增强的模式匹配(JEP 440)提升解构与 switch 表达力;外部函数与内存 API(JEP 442)取代 JNI,实现安全高效的本地调用;还有字符串模板(预览)、分代 ZGC、后量子密钥封装等特性。文中指出了已弃用的 Windows 32‑bit、Applet、Security Manager 等,并给出兼容性检查、虚拟线程与 ZGC 调优建议。通过高并发 Web 服务和 ETL 场景示例,展示新并发模型的实际价值,并展望虚拟线程、模式匹配和 Project Loom 将继续驱动 Java 生态演进。开发团队应尽早评估迁移,以享受长期支持和性能提升。

Java 21 虚拟线程入门与实践

717 阅读

Java 21引入的虚拟线程是轻量级、由JVM调度的线程,创建和切换成本极低,可实现百万级并发。它兼容现有并发API,支持阻塞IO、结构化并发和调试监控。文章展示了在Web服务器、批量处理、微服务等场景的使用示例,提出避免pin、合理使用ThreadLocal、使用ReentrantLock等最佳实践,并提供渐进式迁移方案。虚拟线程解决了传统线程的数量、上下文切换和内存瓶颈,标志着Java并发编程进入新纪元。

Java Record 让数据类更简洁

685 阅读

Java 16 正式引入 Record,提供一种简洁的不可变数据载体。它自动生成 getter、equals、hashCode、toString 与构造函数,省去大量样板代码,字段隐式 final,保证不可变性。仍可定义紧凑构造函数和自定义方法,实现参数校验或业务逻辑。适用于 DTO、复合键、模式匹配等场景,但不宜用于需要继承或可变状态的类(如 JPA 实体)。遵循仅用于简单数据模型的最佳实践,可显著提升代码可读性和安全性。

volatile 如何保证可见性和有序性

705 阅读

Java volatile 是轻量级同步工具,保证对共享变量的写立即刷新到主内存并使其他线程的副本失效,从而实现可见性;通过在读写前后插入内存屏障,阻止指令重排,提供有序性。适合状态标志、一次性安全发布、独立观察等场景,但不保证复合操作的原子性,仍需 synchronized 或原子类。使用条件是写操作不依赖当前值且无需锁保护;相较 synchronized,volatile 读几乎无代价,写略慢但开销远低。正确理解其语义和实现,可在多线程程序中实现高效、可靠的线程间通信。

写一个比 sleep 更好用的延迟工具类

724 阅读

Thread.sleep()需要手动毫秒换算、只能固定时长且抛Checked异常,导致代码冗余易错。文章推出DelayUtils工具类,提供delaySeconds、delayMinutes等多单位方法,内部完成毫秒换算并统一处理InterruptedException,还支持指数退避等动态延迟。相比原生sleep,使用更直观、可读、免异常模板、易扩展,建议在多数需明确单位或复杂重试的场景中替代Thread.sleep()。

Java 17 的 14 个新功能

1359 阅读

2021 年 9 月 14 日发布的 Java 17 是长期支持(LTS)版,带来 14 项新特性:恢复始终严格的浮点语义;新增统一的 RandomGenerator 接口与工厂;在 macOS 上采用 Apple Metal 渲染并支持 AArch64 架构;删除已废弃的 Applet API;加强 JDK 内部封装,取消 --illegal-access 选项;预览 Switch 模式匹配;移除 RMI Activation;正式推出密封类;剔除实验性的 AOT/JIT 编译器;弃用 Security Manager;孵化外部函数与内存 API;二次孵化 Vector API;以及支持基于上下文的反序列化过滤器。全文提供下载链接与官方文档,属 Java 新特性教程系列。

PageHelper结合Lambda表达式实现简洁的分页封装

1123 阅读

本文演示了在Spring Boot 项目中通过引入 `pagehelper‑spring‑boot‑starter`,结合 Java Lambda 表达式,实现统一、简洁的分页封装。首先定义 `BaseQueryParam` 只包含 `pageNum`、`pageSize`,供所有查询继承;随后实现通用的 `NewPageBean<T>`,在 `generatePage` 方法中使用 `PageHelper.startPage(...).doSelectPage(ISelect)` 通过 Lambda 调用 Mapper,自动返回 `total`、`list` 与 `MyPage`(页码、页大小、总页数、前后页)等分页信息。示例代码展示了 `TaskMapper`、对应 XML 与 `TaskController` 的调用方式,访问 `http://localhost:9090/demo/test?pageNum=2&pageSize=2` 即可得到结构化的分页响应。整个方案实现了分页逻辑的高度复用与代码简化。

装饰者模式

1297 阅读

装饰者模式是一种结构型设计模式,通过在运行时为对象动态添加新功能而不修改原类。实现步骤包括:定义Component接口;实现ConcreteComponent;创建实现Component并持有Component引用的抽象Decorator;在ConcreteDecoratorA、ConcreteDecoratorB等具体装饰者中扩展operation方法添加新行为。客户端可通过把装饰者层层包装ConcreteComponent,实现灵活组合行为,体现了装饰者模式在不影响原有对象的前提下增强功能的优势。

单例模式

1271 阅读

单例模式旨在保证一个类只有唯一实例并提供全局访问点。文中介绍了五种常见实现:①懒汉式(非线程安全);②同步懒汉式(通过synchronized保证安全);③双重检查锁定(在必要时同步,性能更佳);④饿汉式(类加载即实例化,天然线程安全);⑤枚举实现(简洁且安全)。每种方案适用于不同的并发需求,开发者应依据实际场景选择最合适的实现方式。