06-Java服务性能排障
Java 服务变慢怎样定位?从 CPU、GC 到内存保留链 服务响应越来越慢,是死循环、频繁 GC、堆外增长,还是等待数据库?一张内存曲线或一行 GC 日志无法回答这些问题。排障需要把系统现象、线程证据和对象保留关系放在同一条推理链上。 CPU、堆转储和 GC 的 Main.java 是三个独立示例
Java 服务变慢怎样定位?从 CPU、GC 到内存保留链 服务响应越来越慢,是死循环、频繁 GC、堆外增长,还是等待数据库?一张内存曲线或一行 GC 日志无法回答这些问题。排障需要把系统现象、线程证据和对象保留关系放在同一条推理链上。 CPU、堆转储和 GC 的 Main.java 是三个独立示例
线程池为什么越调越慢?队列、拒绝与异步任务设计 接口变慢后,把最大线程数调大,结果响应没有改善,内存和下游压力反而升高。线程池是在有限资源下安排工作,不是把所有排队都变成并行执行。理解任务如何进入队列,才能解释参数为什么没有按预期起作用。 1. 先看任务流转,而不是先填参数 线程、队列与拒绝共同形成
并发正确性从哪里来?原子性、可见性与共享状态 给字段加 volatile,计数仍会丢;换成 ConcurrentHashMap,先判断再写入仍可能竞争。问题不在于工具名字是否带 Concurrent,而在于程序需要保护的是单次读写,还是由多次操作组成的业务条件。 1. 拆开一条看起来简单的语句 先看
Java 集合与泛型:怎样把错误挡在编译期? 一个 List 可以编译,却在读取时抛出类型转换异常;一个 LinkedList 声称擅长插入,却在按下标循环时越来越慢。集合选择和类型设计不是互不相关的知识点,它们共同决定接口允许什么,以及操作需要付出什么成本。 1. 操作方式决定容器成本 先按访问、
HashMap 为什么会查不到?从键的契约到扩容机制 同一个对象明明已经放进 HashMap,get 却返回 null;两个键发生冲突,又为什么不会直接覆盖?这两种现象指向不同层次:对象先决定怎样相等,集合再决定到哪里寻找。本文把键的契约与存储过程串起来,避免把 hashCode、数组下标和业务编号