CPU 100% 故障定位指导手册

适用场景: 告警系统上报 CPU 使用率超过阈值, 需逐层定位至代码行级 前置知识: Linux 进程/线程模型, CPU 时间片调度, JVM 线程模型 一、为什么需要四层诊断模型 1.1 理论依据: 故障定位的"层级原则" 一个 CPU 告警可能由多个层面的问题引起, 每一层需要不同的工具来观测: 系统层 (kernel) → /proc/stat, vmstat — 看调度队列和 CPU 时间分配 进程层 (process) → top, /proc/<pid>/stat — 看进程级别的 CPU 消耗 线程层 (thread) → top -H, /proc/<pid>/task — 看线程级别的 CPU 消耗 代码层 (code) → jstack, perf, Arthas — 看具体的执行方法/指令 选择依据: 每一层只看上一层无法提供的信息。系统层告诉你"CPU 在忙", 但不告诉你是谁; 进程层告诉你"是 PID 172 在忙", 但如果你直接跳到代码层(比如盲目 jstack), 你拿到 30 个线程的栈, 却不知道该看哪一个——这就是为什么需要线程层: 先找到具体的线程 TID, 再精准定位。 ...

2026-06-13 · 陈曦

在Java中写一个正确的单例模式

本文参考极客时间每日一课《在Java中如何写一个正确的单例模式?》 1. 单例/单例设计模式 一个类只允许创建一个对象(实例),这个类就是一个单例类。这种设计模式叫做单例设计模式,简称单例模式。 实现一个单例类,需要关注: 构造函数私有,避免通过new关键字创建实例 创建时的线程安全问题 是否支持延迟加载 getInstance是否高性能(锁) 2. 单例模式的写法 2.1. 饿汉式 public class Singleton { private static final Singleton INSTANCE = new Singleton(); private Singleton() { } public static Singleton getInstance() { return INSTANCE; } } public class Singleton { private static Singleton instance; static { instance = new Singleton(); } private Singleton() {} public static Singleton getInstance() { return instance; } } 类加载时,静态实例就已经创建好并初始化好了。 ...

2021-11-19 · 陈曦

GC日志解读

为深入学习GC(Garbage Collection,垃圾回收),本文将使用一段测试代码来测试不同的GC策略下的执行情况,并对输出的GC日志做简要分析。 1. 测试环境 1.1. 操作系统及jdk版本 ➜ 01jvm git:(main) ✗ java -version java version "1.8.0_131" Java(TM) SE Runtime Environment (build 1.8.0_131-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode) 1.2. 测试代码 测试代码来源: https://github.com/JavaCourse00/JavaCourseCodes/blob/main/01jvm/GCLogAnalysis.java import java.util.Random; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.LongAdder; /* 演示GC日志生成与解读 */ public class GCLogAnalysis { private static Random random = new Random(); public static void main(String[] args) { // 当前毫秒时间戳 long startMillis = System.currentTimeMillis(); // 持续运行毫秒数; 可根据需要进行修改 long timeoutMillis = TimeUnit.SECONDS.toMillis(1); // 结束时间戳 long endMillis = startMillis + timeoutMillis; LongAdder counter = new LongAdder(); System.out.println("正在执行..."); // 缓存一部分对象; 进入老年代 int cacheSize = 2000; Object[] cachedGarbage = new Object[cacheSize]; // 在此时间范围内,持续循环 while (System.currentTimeMillis() < endMillis) { // 生成垃圾对象 Object garbage = generateGarbage(100*1024); counter.increment(); int randomIndex = random.nextInt(2 * cacheSize); if (randomIndex < cacheSize) { cachedGarbage[randomIndex] = garbage; } } System.out.println("执行结束!共生成对象次数:" + counter.longValue()); } // 生成对象 private static Object generateGarbage(int max) { int randomSize = random.nextInt(max); int type = randomSize % 4; Object result = null; switch (type) { case 0: result = new int[randomSize]; break; case 1: result = new byte[randomSize]; break; case 2: result = new double[randomSize]; break; default: StringBuilder builder = new StringBuilder(); String randomString = "randomString-Anything"; while (builder.length() < randomSize) { builder.append(randomString); builder.append(max); builder.append(randomSize); } result = builder.toString(); break; } return result; } } 编译测试代码 ...

2021-06-05 · 陈曦