Lombok 拾遗
Created|Updated|Java
|Word Count:43|Reading Time:1mins|Post Views:
sneakyThrow
1 | |
Author: magicliang
Copyright Notice: All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.
Related Articles
2026-05-21
回到工程:计算理论怎样改变写代码的眼光
这个系列从《计算的本质》重新出发,用 Python 重写核心实验,再把每个模型映射到 Java 程序员熟悉的工程结构。一路走下来,主题并不是记住更多术语,而是换一种方式观察程序。 程序可以是语法树,执行可以是规约,协议可以是自动机,嵌套可以靠栈,通用计算可以由解释器承载,分析工具也可以承认不精确并保持有用。 本文不再引入新模型,只把前面十几篇文章收束成一张工程地图。 概念地图 先把系列里最重要的模型压成一段可运行的概念地图。 12345678910concept_map = [ ("AST / 语义", "解释器、DSL、规则执行"), ("DFA / NFA / 正则", "协议状态、校验器、词法分析"), ("PDA / 栈", "parser、嵌套结构、调用栈"), ("图灵机 / 通用性", "VM、脚本引擎、程序作为数据"), ("停机问题 / 抽象解释", &...
2025-07-29
HTTP 请求体只读一次之谜——Go 与 Java 的应对之道
在后端开发中,日志记录、签名验证、请求重放等场景都需要在中间件(Middleware/Filter)中读取 HTTP 请求体(Request Body)。然而,请求体在被读取一次后便无法再次获取——后续处理程序收到的是一个空的 Body,导致逻辑中断。 这并非 Bug,而是网络 I/O 流处理的基本特性。本文将从操作系统内核的 Socket 缓冲区出发,剖析这一现象的根源,并详细对比 Go 和 Java 在"可重复读 Body"问题上的解决方案及其背后截然不同的设计哲学。 第一部分:问题的根源——流的"阅后即焚"本质 为什么 HTTP 请求体默认只能读取一次? 请求体本质上是一个从网络连接中实时到达的字节流,而非一块已经完整存放在内存或磁盘上的数据块。理解这一点是理解"只读一次"问题的关键。 操作系统层面:Socket 读取缓冲区 当客户端发送 HTTP 请求时,数据通过 TCP 连接到达服务器的网络套接字(Socket)。操作系统内核维护着一个接收缓冲区(Receive Buffer),TCP 数据包到达后被暂存在这里...
2025-07-29
MESI 协议与 Java 并发可见性——从硬件到 JMM
为什么 volatile 能保证可见性?为什么 synchronized 既保证原子性又保证可见性?答案藏在 CPU 缓存一致性协议和内存屏障中。本文将从硬件层面的 MESI 协议出发,逐步上升到 Java 内存模型(JMM),揭示并发可见性问题的完整因果链。 Part 1: CPU 缓存架构 为什么需要 CPU 缓存 现代 CPU 的运算速度远超内存访问速度,两者之间存在巨大的速度鸿沟: 操作 延迟 相对速度 CPU 寄存器访问 ~0.3 ns 1x L1 Cache 访问 ~1 ns 3x L2 Cache 访问 ~4 ns 13x L3 Cache 访问 ~12 ns 40x 主内存访问 ~100 ns 333x 如果 CPU 每次都直接访问主内存,大部分时间都在等待数据。缓存利用了时间局部性和空间局部性,将最近和附近的数据保存在更快的存储中。 多级缓存架构 12345678910111213141516171819┌──────────────────────────────────────────────────────┐│ ...
2026-05-21
停机问题:为什么某些判断没有通用程序
上一篇文章用寄存器机解释器说明了通用性:程序可以编码成数据,解释器可以读取这份数据并模拟执行。通用性带来强大表达能力,也带来一个边界问题:能不能写一个程序,判断任意程序在任意输入上是否会停机。 答案是否定的。停机问题说明,不存在一个对所有程序和输入都正确的通用停机判定器。工程里可以做超时、步数限制、静态分析和资源预算,但这些方法要么不完整,要么会保守拒绝,要么只覆盖有限范围。 本文先用一个可运行的有界检查器展示工程近似,再用自引用反证解释为什么通用判定器不存在。 问题形式 停机问题可以写成一个理想函数: 1halts(program, input_data) -> True / False 它的承诺是: 返回值 含义 True program(input_data) 最终会停机 False program(input_data) 会一直运行 难点在“任意程序”和“任意输入”。判断某个具体程序很容易;判断所有程序则会遇到自引用。 工程里常见的近似:有界执行 最朴素的方法是只运行有限步。如果步数内停机,就返回 True;如果步数用完还没停,就返回 Fa...

2020-04-16
Spark SQL 原理
Spark SQL的发展历程 为了给熟悉的 RDBMS 但又不理解 MapReduce 的技术人员提供快速上手的工具,Hive 应运而生,他是当时唯一运行在 Hadoop 上的SQL-On-Hadoop 工具。 但是 MapReduce 计算过程中大量的中间磁盘落地过程消耗了大量的 I/O,降低的运行效率,为了提高 SQL 的执行效率,大量的 SQL-On-Hadoop工具开始产生,而 Shark 是其中一个表现较为突出的项目。 Shark是伯克利实验室 Spark 生态环境的组件之一,它主要修改了内存管理,物理计划和执行三个模块,值得它能运行在 Spark 的引擎上,从而提高 SQL 查询的效率。 但是随着 Spark 的发展,Shark 对 Hive 过多的依赖制约了 Spark 的设计理念和各个组件之间的相互继承,所以 Spark 团队停止了对 Shark 的开发,提出了 SparkSQL 项目。 因为摆脱了Hive 的过度依赖,Spark SQL在数据兼容性,性能优化和组件扩展等各个方面都得到了极大的方便和发展。 提出了 SparkSQL 项目之后,SQL On Spar...
2026-05-21
非确定性有限自动机:一次保留多个可能世界
DFA 每次只处在一个状态里。读取一个字符,规则表给出唯一的下一个状态。这个约束让 DFA 很容易实现,也让它的执行轨迹很干净:current_state + character -> next_state。 非确定性有限自动机(Nondeterministic Finite Automaton,NFA)放宽了这个约束。同一个状态读取同一个字符时,可以走到多个下一状态;机器还可以在不消耗字符的情况下移动到别的状态。NFA 的实现方式并不神秘:把“当前状态”从单个值改成一个集合,一次保留所有可能路径。 这篇文章用 Python 写一个 NFA,识别两个字符串:ab 和 ba。这个示例足够小,但能完整覆盖 NFA 的两个核心机制:分支和空转移。 非确定性不是随机 “非确定性”容易被误解成机器随机选择一条路。NFA 的更好理解是:同一时刻保留多条候选路径,只要其中一条路径最后进入接受状态,整个输入就被接受。 问题 DFA NFA 当前状态 一个状态 一组状态 同一输入的下一状态 唯一 可以有多个 是否允许不读字符就移动 不允许 允许 接受条件 当前状态...
Contents
