JVM 的内存模型与线程
JVM 的内存模型与线程 Java 内存模型(Java Memory Model, JMM)定义了多线程环境下共享变量的访问规则,是理解并发编程的基石。本文从硬件架构出发,逐步深入到 JMM 的核心机制与实践模式。 mindmap root((JMM)) 硬件基础 CPU缓存层次 缓存一致性协议 JMM 抽象 主内存 vs 工作内存 八种内存操作 happens-before 关系 关键保证 原子性 可见性 有序性 实践工具 volatile synchronized final 模式总览 # 模式名称 一句话口诀 适用场景 1 写刷读清 写入即刷盘,读取先清空 volatile / unlock 后的可见性 2 顺序锁 同把锁内,串行执行 synchronized 临界区保护 3 偏序传递 A先于B,B先于C,则A先于C happens-before 链式推理 4 不可变安全 构造完成前...
Maven 完全指南
本文整合了 Maven 构建生命周期、插件配置、依赖管理、全局配置 settings.xml、FatJar 打包、测试与覆盖率等全部知识点,是一份系统性的 Maven 参考指南。 maven-生命周期.xmind 构建生命周期 构建生命周期的基础知识 Maven 基于一个"构建生命周期"的中心概念,也就意味着构建和发布一个特定的工件(也就是工程)的过程已经被清晰地定义了。 有三种内置的生命周期:default,clean 和 site。default 生命周期处理项目部署,clean 生命周期处理项目清理,site 生命周期处理项目的站点(site)文档的创建。 graph TD subgraph Clean生命周期 A1[pre-clean] --> A2[clean] A2 --> A3[post-clean] end subgraph Default生命周期 B1[validate] --> B2[initialize] B2 -->...
Docker 完全指南
第1章:Docker 核心架构 Docker 是一种操作系统级别的虚拟化技术,它通过 Linux 内核的多项特性实现进程间的软隔离,而非传统虚拟机的硬件级虚拟化。理解 Docker 的核心架构,是掌握容器技术的第一步。 Docker 的四根柱子 Docker 的核心技术基于 Linux 内核的三大特性,加上一个标准化的容器格式: 1. Namespace(命名空间)—— 隔离 Namespace 是 Linux 内核提供的资源隔离机制,Docker 利用它为每个容器创建独立的运行环境。Docker 使用的 Namespace 包括: Namespace 隔离内容 说明 PID 进程 ID 容器内的进程有独立的 PID 空间 NET 网络 独立的网络栈、IP 地址、端口 MNT 文件系统挂载点 独立的文件系统视图 UTS 主机名和域名 容器可以有自己的主机名 IPC 进程间通信 独立的信号量、消息队列 USER 用户和用户组 容器内的 root 可以映射为宿主机的普通用户 2. Control Group(cgroup)—— 资源限制 cgr...
Guava 解析
前言 Guava 本身适配不同的环境,Jdk 1.8 以上使用 jre flavor,Jdk 1.7 和 android 使用 android flavor。 类库的作者,不要使用 @Beta 成员,以后它们不会是 source-compatible。但我们可以使用其他成员,它们会是 binary-compatible,Guava 现在不会再因为非安全原因删除成员了,即使是 @Deprecated 的。 可用的功能见这个 User Guide。 common Collect 不可变集合 Guava 提供了强类型的不可变集合,这些集合一旦创建就不能被修改,非常适合用于构建线程安全的应用和防御性编程。 1234567891011121314151617181920212223242526import com.google.common.collect.ImmutableList;import com.google.common.collect.ImmutableSet;import com.google.common.collect.ImmutableMap;// 创建不可变 Lis...
一致性哈希与数据分片
数据分片的动机 随着互联网应用的快速发展,数据量和访问量呈现爆炸式增长。单机存储系统面临着两个根本性的瓶颈:存储容量和访问性能。 存储容量方面,单台服务器的磁盘空间是有限的。当数据量超过单机容量时,必须寻找横向扩展的解决方案。垂直扩展通过升级硬件配置可以在一定程度上缓解问题,但成本高昂且存在物理上限。更重要的是,单机无法无限扩展,当数据量达到TB甚至PB级别时,垂直扩展已经无法满足需求。 访问性能方面,单机的处理能力同样有限。随着用户数量和请求量的增加,CPU计算能力、内存带宽、磁盘I/O和网络带宽都会成为性能瓶颈。即使单机能够处理当前的负载,也无法保证未来业务的持续增长。 数据分片提供了一种水平扩展的解决方案。通过将数据分散到多台服务器上,每台服务器只存储部分数据并处理部分请求,从而实现存储容量和访问性能的线性扩展。这种架构具有更好的可扩展性,可以根据业务增长灵活地增加服务器节点。 朴素哈希分片 朴素哈希分片是最直观的数据分片方案。其核心思想是:对于给定的数据键key,通过哈希函数计算其哈希值,然后对节点数量N取模,确定该数据应该存储在哪个节点。 1node_index = h...
API 兼容性设计
在软件工程中,API 兼容性是一个至关重要但又经常被忽视的问题。良好的兼容性设计能够确保系统的平滑演进,避免因 API 变更导致的客户端崩溃和服务中断。本文将从多个维度探讨 API 兼容性设计的最佳实践。 什么是 API 兼容性 API 兼容性分为两种类型: 向前兼容:旧版本的客户端能够与新版本的服务端正常通信。即服务端升级后,旧客户端仍能正常工作。 向后兼容:新版本的客户端能够与旧版本的服务端正常通信。即客户端升级后,旧服务端仍能提供服务。 在实际项目中,我们通常更关注向前兼容,因为服务端的升级往往不可控,而客户端的更新节奏各异。 破坏性变更的分类 破坏性变更是指会导致现有客户端无法正常工作的 API 变更。主要分为三类: 1. 接口签名变更 123456789// 变更前public interface UserService { User getUser(String userId);}// 变更后 - 破坏性变更public interface UserService { User getUser(String userId,...
重读 Eric Evans 的 DDD 蓝皮书
引言 软件系统的复杂性往往被误解为技术问题。在多年的开发实践中,我们习惯了用各种设计模式、架构框架、技术栈来应对复杂性,却忽略了一个根本事实:软件的核心复杂性在于领域本身,而非技术实现。Eric Evans 在《领域驱动设计》一书中提出了这一深刻见解,并给出了一套系统化的方法论——领域驱动设计。 DDD 不是一套必须严格遵守的规范,也不是一个可以简单套用的框架,它是一种思维方式,一种通过深入理解业务领域来构建高质量软件的方法论。重读这本经典著作,让我们重新审视这些核心理念。 通用语言 通用语言是 DDD 的基石。开发团队与领域专家共享同一套语言,这套语言不仅用于沟通,也体现在代码中。代码即文档,文档即代码。 在传统开发模式中,业务专家使用业务术语,技术人员使用技术术语,两者之间存在天然的语言鸿沟。业务需求被翻译成技术文档,技术文档又被翻译成代码,每个翻译环节都会产生信息丢失和误解。通用语言的提出,就是为了消除这种鸿沟。 通用语言应该由开发和业务专家共同构建,在持续的交流中不断完善。它体现在所有方面:需求讨论、文档、代码、测试。当领域专家能够阅读代码并理解其含义时,当开发人员能够直...
HTTP/1.1 到 HTTP/3 的演进
引言 HTTP 协议作为现代互联网的基石,自 1991 年诞生以来经历了多次重大演进。从最初简单的请求-响应模型,到如今高效、安全的 HTTP/3,每一次版本更新都针对前一版本的局限性进行了针对性的改进。本文将系统性地梳理 HTTP/1.0、HTTP/1.1、HTTP/2 和 HTTP/3 的核心技术特性和演进路径,深入分析每一代协议的设计理念、性能优化以及面临的挑战。 HTTP/1.0 的局限性 HTTP/1.0 于 1996 年发布,奠定了现代 Web 通信的基础框架。然而,随着互联网应用的快速发展,HTTP/1.0 的局限性逐渐显现。 每个 TCP 连接只能处理一个请求 HTTP/1.0 采用最简单的请求-响应模型:客户端发起请求,建立 TCP 连接,服务器返回响应后关闭连接。对于包含多个资源(如 HTML、CSS、JavaScript、图片等)的网页,浏览器需要为每个资源建立独立的 TCP 连接。这种模式带来了严重的性能问题: TCP 连接建立和关闭需要消耗系统资源 三次握手和慢启动机制增加了延迟 无法充分利用网络带宽 缺乏 Host 头字段 HTTP/1.0 最初设...
Java 结构化并发
结构化并发(Structured Concurrency) 结构化并发是 Java 并发编程的重要演进方向,与虚拟线程紧密配合,旨在解决传统并发编程中的线程泄漏、错误处理困难等问题。 1. 历史背景 1.1 结构化并发的起源与核心类比 术语起源 “结构化并发”(Structured Concurrency)这个术语由 Martin Sústrik(ZeroMQ 作者)在 2016 年首次提出。随后,Nathaniel J. Smith 在 2018 年发表了著名的文章《Notes on structured concurrency, or: Go statement considered harmful》,系统性地阐述了结构化并发的理论基础。 timeline title 结构化并发发展历程 2016 : Martin Sústrik 首创术语 : 在 250bpm.com 发表系列文章 2018 : Nathaniel J. Smith 发表核心论文 : "Go statement considered ha...
G1/ZGC/Shenandoah 垃圾收集器对比
垃圾收集的核心挑战 垃圾收集器的设计始终面临三个核心指标的权衡:吞吐量、延迟和内存占用。这三个指标构成了一个不可能三角,优化其中一个指标往往需要牺牲其他指标。 吞吐量指单位时间内完成的工作量,通常用应用程序运行时间占总时间的比例来衡量。对于批处理任务、科学计算等场景,高吞吐量是首要目标。 延迟指垃圾收集造成的应用停顿时间。对于交互式应用、金融交易系统等对响应时间敏感的场景,低延迟至关重要。延迟通常关注最大停顿时间和停顿时间分布。 内存占用指垃圾收集器为了完成收集工作所需的额外内存空间。内存受限的环境下,收集器自身的内存开销成为关键约束。 传统垃圾收集器在三者之间做出明确取舍:Serial 和 Parallel GC 追求高吞吐量,但停顿时间较长;CMS GC 降低停顿时间,但牺牲吞吐量并占用更多内存。现代收集器试图在三者之间找到更优的平衡点。 G1(Garbage First)收集器 G1 收集器在 JDK 7u4 版本正式推出,是 JDK 9 之后的默认垃圾收集器。G1 的核心思想是打破传统分代收集的物理隔离,将堆内存划分为多个大小相等的 Region。 Region 化堆内存...










