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