[{"data":1,"prerenderedAt":574},["ShallowReactive",2],{"java-doc-count":3},[4,128,204,291,367,477],{"id":5,"title":6,"body":7,"commentId":115,"description":116,"difficulty":117,"draft":118,"extension":119,"meta":120,"navigation":121,"order":110,"path":122,"section":123,"seo":124,"stem":125,"updated":126,"__hash__":127},"java\u002Fjava\u002Fconcurrency.md","Java 并发知识地图",{"type":8,"value":9,"toc":103},"minimark",[10,14,18,27,30,40,43,46,49,85,88],[11,12,13],"h2",{"id":13},"并发问题的三个核心维度",[15,16,17],"h3",{"id":17},"可见性",[19,20,21,22,26],"p",{},"一个线程修改的数据，何时能够被另一个线程观察到。",[23,24,25],"code",{},"volatile","、锁和线程启动\u002F终止规则都与 happens-before 有关。",[15,28,29],{"id":29},"原子性",[19,31,32,33,36,37,39],{},"一个操作能否被其他线程观察到中间状态。",[23,34,35],{},"count++"," 即使使用 ",[23,38,25],{}," 也不是原子操作。",[15,41,42],{"id":42},"有序性",[19,44,45],{},"编译器和处理器可以在不改变单线程结果的前提下重排序。并发程序必须通过同步规则建立必要顺序。",[11,47,48],{"id":48},"知识路线",[50,51,52,56,61,67,70,73,76,82],"ol",{},[53,54,55],"li",{},"Java 内存模型与 happens-before",[53,57,58,60],{},[23,59,25],{}," 与内存屏障",[53,62,63,66],{},[23,64,65],{},"synchronized"," 与对象监视器",[53,68,69],{},"CAS、原子类和 ABA 问题",[53,71,72],{},"AQS、锁和同步器",[53,74,75],{},"线程池与任务调度",[53,77,78,81],{},[23,79,80],{},"CompletableFuture"," 与异步编排",[53,83,84],{},"并发容器",[11,86,87],{"id":87},"生产实践原则",[89,90,91,94,97,100],"ul",{},[53,92,93],{},"尽量减少共享可变状态。",[53,95,96],{},"明确线程池的职责、队列容量和拒绝策略。",[53,98,99],{},"不要把耗时不可控的任务提交到公共线程池。",[53,101,102],{},"监控活跃线程数、队列长度、拒绝次数和任务耗时。",{"title":104,"searchDepth":105,"depth":105,"links":106},"",2,[107,113,114],{"id":13,"depth":105,"text":13,"children":108},[109,111,112],{"id":17,"depth":110,"text":17},3,{"id":29,"depth":110,"text":29},{"id":42,"depth":110,"text":42},{"id":48,"depth":105,"text":48},{"id":87,"depth":105,"text":87},"wiki:java:concurrency","理解可见性、原子性、有序性，以及 Java 并发工具如何建立在这些规则之上。","intermediate",false,"md",{},true,"\u002Fjava\u002Fconcurrency","并发编程",{"title":6,"description":116},"java\u002Fconcurrency","2026-07-10","EkMZP12_4LdF-05WBbKP344weaqz3uif-3l5nazF3xk",{"id":129,"title":130,"body":131,"commentId":195,"description":196,"difficulty":117,"draft":118,"extension":119,"meta":197,"navigation":121,"order":198,"path":199,"section":200,"seo":201,"stem":202,"updated":126,"__hash__":203},"java\u002Fjava\u002Fdatabase.md","数据库与缓存知识地图",{"type":8,"value":132,"toc":189},[133,136,139,143,163,166,183,186],[11,134,135],{"id":135},"数据库知识的核心问题",[19,137,138],{},"后端开发关注的不只是 SQL 能否执行，还要理解数据如何被定位、并发修改如何协调、失败后如何恢复，以及缓存加入后怎样维持可接受的一致性。",[11,140,142],{"id":141},"mysql","MySQL",[89,144,145,148,151,154,157,160],{},[53,146,147],{},"B+Tree 与索引组织",[53,149,150],{},"联合索引和最左匹配",[53,152,153],{},"执行计划",[53,155,156],{},"MVCC 与 Read View",[53,158,159],{},"行锁、间隙锁和死锁",[53,161,162],{},"redo log、undo log 与 binlog",[11,164,165],{"id":165},"缓存",[89,167,168,171,174,177,180],{},[53,169,170],{},"Cache Aside",[53,172,173],{},"缓存穿透、击穿和雪崩",[53,175,176],{},"热点 Key",[53,178,179],{},"数据更新与失效",[53,181,182],{},"最终一致性",[11,184,185],{"id":185},"排查顺序",[19,187,188],{},"面对慢查询，先确认实际执行 SQL 和参数，再看执行计划、扫描行数、锁等待和数据分布。不要只根据 SQL 外观判断是否使用索引。",{"title":104,"searchDepth":105,"depth":105,"links":190},[191,192,193,194],{"id":135,"depth":105,"text":135},{"id":141,"depth":105,"text":142},{"id":165,"depth":105,"text":165},{"id":185,"depth":105,"text":185},"wiki:java:database","围绕索引、事务、锁、缓存与数据一致性，建立后端开发需要的数据库认知。",{},5,"\u002Fjava\u002Fdatabase","数据库",{"title":130,"description":196},"java\u002Fdatabase","3gza7dGQZPwMSHFISiZ7Jy-iB_2rQD2ozomZ8OuiyHw",{"id":205,"title":206,"body":207,"commentId":281,"description":282,"difficulty":283,"draft":118,"extension":119,"meta":284,"navigation":121,"order":285,"path":286,"section":287,"seo":288,"stem":289,"updated":126,"__hash__":290},"java\u002Fjava\u002Ffundamentals.md","Java 基础知识地图",{"type":8,"value":208,"toc":275},[209,212,215,217,240,243,246,249],[11,210,211],{"id":211},"这一部分解决什么问题",[19,213,214],{},"Java 基础不是 API 的罗列，而是理解类型、对象和运行时行为之间的关系。后续的并发、JVM 和框架知识都建立在这些概念之上。",[11,216,48],{"id":48},[50,218,219,222,228,231,234,237],{},[53,220,221],{},"基本类型、包装类型与自动装箱",[53,223,224,227],{},[23,225,226],{},"String","、不可变对象与对象比较",[53,229,230],{},"集合框架与常见数据结构",[53,232,233],{},"泛型、类型擦除与边界",[53,235,236],{},"反射、注解与动态代理",[53,238,239],{},"异常体系和资源管理",[11,241,242],{"id":242},"推荐学习方式",[19,244,245],{},"先用一句话回答“它是什么”，再通过小段代码验证边界，最后把它放回 JVM 和框架运行机制中理解。知识库会逐步把每个主题拆成独立条目。",[11,247,248],{"id":248},"面试时容易出现的问题",[89,250,251,258,269,272],{},[53,252,253,254,257],{},"只背诵 ",[23,255,256],{},"HashMap"," 的结论，不理解哈希冲突和扩容成本。",[53,259,260,261,264,265,268],{},"把 ",[23,262,263],{},"=="," 和 ",[23,266,267],{},"equals"," 简化成“地址比较”和“内容比较”。",[53,270,271],{},"知道泛型语法，但无法解释类型擦除带来的限制。",[53,273,274],{},"会使用反射，却不了解它为什么被 Spring 等框架广泛使用。",{"title":104,"searchDepth":105,"depth":105,"links":276},[277,278,279,280],{"id":211,"depth":105,"text":211},{"id":48,"depth":105,"text":48},{"id":242,"depth":105,"text":242},{"id":248,"depth":105,"text":248},"wiki:java:fundamentals","Java 类型系统、集合、泛型、反射、异常与常用语言机制的学习入口。","basic",{},1,"\u002Fjava\u002Ffundamentals","Java 基础",{"title":206,"description":282},"java\u002Ffundamentals","TZ18cq4bXSr9iscSOTSlgfMfbmTp2H5kOdVxAbnY_2s",{"id":292,"title":293,"body":294,"commentId":358,"description":359,"difficulty":283,"draft":118,"extension":119,"meta":360,"navigation":121,"order":361,"path":362,"section":363,"seo":364,"stem":365,"updated":126,"__hash__":366},"java\u002Fjava\u002Finterview.md","Java 面试专题使用说明",{"type":8,"value":295,"toc":353},[296,299,302,305,338,341,350],[11,297,298],{"id":298},"这里不会做什么",[19,300,301],{},"不会把数百道问题堆在一个页面，也不会只给出适合背诵但无法解释的标准答案。",[11,303,304],{"id":304},"每个问题的组织方式",[50,306,307,314,320,326,332],{},[53,308,309,313],{},[310,311,312],"strong",{},"一句话回答","：先准确回答问题。",[53,315,316,319],{},[310,317,318],{},"核心原理","：说明这个结论为什么成立。",[53,321,322,325],{},[310,323,324],{},"代码验证","：使用尽可能小的例子验证边界。",[53,327,328,331],{},[310,329,330],{},"常见误区","：指出容易混淆的地方。",[53,333,334,337],{},[310,335,336],{},"继续追问","：把当前问题连接到更深层知识。",[11,339,340],{"id":340},"示例追问链",[342,343,348],"pre",{"className":344,"code":346,"language":347,"meta":104},[345],"language-text","HashMap 为什么线程不安全？\n  → put 操作包含哪些步骤？\n  → 扩容时发生什么？\n  → ConcurrentHashMap 如何降低竞争？\n  → JDK 不同版本的实现有什么变化？\n","text",[23,349,346],{"__ignoreMap":104},[19,351,352],{},"面试题的价值不是预测题目，而是帮助自己检查知识之间是否已经形成连接。",{"title":104,"searchDepth":105,"depth":105,"links":354},[355,356,357],{"id":298,"depth":105,"text":298},{"id":304,"depth":105,"text":304},{"id":340,"depth":105,"text":340},"wiki:java:interview","用简明回答、原理解释、代码验证和追问路径组织 Java 面试知识。",{},6,"\u002Fjava\u002Finterview","面试专题",{"title":293,"description":359},"java\u002Finterview","AWxAYmdi1IahbXu7QwVZPfsiCXbVU4YTMMoshQkzEl8",{"id":368,"title":369,"body":370,"commentId":469,"description":470,"difficulty":117,"draft":118,"extension":119,"meta":471,"navigation":121,"order":105,"path":472,"section":473,"seo":474,"stem":475,"updated":126,"__hash__":476},"java\u002Fjava\u002Fjvm.md","JVM 知识地图",{"type":8,"value":371,"toc":459},[372,376,379,381,384,398,401,415,418,432,435,449,452],[11,373,375],{"id":374},"为什么要理解-jvm","为什么要理解 JVM",[19,377,378],{},"JVM 把 Java 源代码和具体硬件隔开，但生产问题最终仍会落到内存、线程、字节码和操作系统资源上。理解 JVM 的目标不是记参数，而是能解释和诊断程序行为。",[11,380,48],{"id":48},[15,382,383],{"id":383},"类加载",[89,385,386,389,392,395],{},[53,387,388],{},"加载、验证、准备、解析和初始化",[53,390,391],{},"双亲委派模型",[53,393,394],{},"类加载器隔离",[53,396,397],{},"静态字段和初始化顺序",[15,399,400],{"id":400},"运行时数据区",[89,402,403,406,409,412],{},[53,404,405],{},"堆与对象分配",[53,407,408],{},"虚拟机栈与栈帧",[53,410,411],{},"方法区与元空间",[53,413,414],{},"直接内存",[15,416,417],{"id":417},"垃圾回收",[89,419,420,423,426,429],{},[53,421,422],{},"可达性分析",[53,424,425],{},"分代收集",[53,427,428],{},"CMS、G1 与现代收集器",[53,430,431],{},"停顿时间、吞吐量和内存占用之间的权衡",[15,433,434],{"id":434},"性能排查",[89,436,437,440,443,446],{},[53,438,439],{},"GC 日志",[53,441,442],{},"线程快照",[53,444,445],{},"堆转储",[53,447,448],{},"CPU、内存和锁竞争定位",[11,450,451],{"id":451},"一句话原则",[19,453,454,455,458],{},"先确定现象属于 CPU、内存、线程还是外部依赖，再选择工具；不要看到 ",[23,456,457],{},"OutOfMemoryError"," 就先调整堆大小。",{"title":104,"searchDepth":105,"depth":105,"links":460},[461,462,468],{"id":374,"depth":105,"text":375},{"id":48,"depth":105,"text":48,"children":463},[464,465,466,467],{"id":383,"depth":110,"text":383},{"id":400,"depth":110,"text":400},{"id":417,"depth":110,"text":417},{"id":434,"depth":110,"text":434},{"id":451,"depth":105,"text":451},"wiki:java:jvm","从类加载、运行时内存到垃圾回收与性能排查，理解 Java 程序如何真正运行。",{},"\u002Fjava\u002Fjvm","JVM",{"title":369,"description":470},"java\u002Fjvm","ZPK0OT5czgBvYvU-AowqKfXfaGqS5bqnDP2N5bWKN5k",{"id":478,"title":479,"body":480,"commentId":565,"description":566,"difficulty":117,"draft":118,"extension":119,"meta":567,"navigation":121,"order":568,"path":569,"section":570,"seo":571,"stem":572,"updated":126,"__hash__":573},"java\u002Fjava\u002Fspring.md","Spring 知识地图",{"type":8,"value":481,"toc":558},[482,486,489,493,510,514,528,531,548,551],[11,483,485],{"id":484},"理解-spring-的主线","理解 Spring 的主线",[19,487,488],{},"Spring 的核心不是注解数量，而是容器如何创建对象、建立依赖，并在合适的扩展点改变对象行为。",[11,490,492],{"id":491},"ioc-容器","IOC 容器",[89,494,495,498,501,504,507],{},[53,496,497],{},"BeanDefinition 的来源",[53,499,500],{},"Bean 创建生命周期",[53,502,503],{},"依赖注入",[53,505,506],{},"BeanPostProcessor",[53,508,509],{},"循环依赖",[11,511,513],{"id":512},"aop","AOP",[89,515,516,519,522,525],{},[53,517,518],{},"JDK 动态代理和 CGLIB",[53,520,521],{},"切点与通知",[53,523,524],{},"代理对象调用边界",[53,526,527],{},"自调用为什么可能导致切面失效",[11,529,530],{"id":530},"事务",[89,532,533,536,539,542,545],{},[53,534,535],{},"事务管理器",[53,537,538],{},"传播行为",[53,540,541],{},"隔离级别",[53,543,544],{},"回滚规则",[53,546,547],{},"声明式事务失效场景",[11,549,550],{"id":550},"学习建议",[19,552,553,554,557],{},"选择一条最短链路，从 ",[23,555,556],{},"ApplicationContext"," 启动到一个带事务的 Service 被调用，跟踪其中的对象创建、代理生成和拦截过程。这样比孤立背诵源码类名更有效。",{"title":104,"searchDepth":105,"depth":105,"links":559},[560,561,562,563,564],{"id":484,"depth":105,"text":485},{"id":491,"depth":105,"text":492},{"id":512,"depth":105,"text":513},{"id":530,"depth":105,"text":530},{"id":550,"depth":105,"text":550},"wiki:java:spring","从 IOC、AOP 和事务出发，理解 Spring 如何组织和增强应用程序。",{},4,"\u002Fjava\u002Fspring","Spring",{"title":479,"description":566},"java\u002Fspring","jZmHr0WwrtcGUGlcEdj8z-shlR3YZc-UdEZSfPZYgNE",1783807996432]