Skip to content

提高服务器CPU使用率小工具

约 704 字大约 2 分钟

工具

2025-07-23

如果CPU的使用率没有达到30%,则可以启动工具,使其占用率达到30%

添加依赖

<dependency>
    <groupId>com.github.oshi</groupId>
    <artifactId>oshi-core</artifactId>
    <version>6.8.2</version>
</dependency>

实现代码

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;

import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 如果CPU的使用率没有达到30%,则启动一个CPU密集型任务,使其占用率达到30%
 *
 * @author yunze
 * @apiNote 启动该任务需要再application.yml配置文件里配置task.cpuUsage.enabled=true,该任务默认是不启动的。
 * @since 2025/7/23 14:33
 */
@ConditionalOnProperty(name = "task.cpuUsage.enabled", havingValue = "true", matchIfMissing = false)
@Component
public class OshiScheduler {

    // 目标 CPU 使用率(30%)
    private static final double TARGET_CPU_USAGE = 0.3;
    // 线程池
    private static final ExecutorService executor = Executors.newCachedThreadPool();
    // 任务运行状态
    private static final AtomicBoolean running = new AtomicBoolean(true);
    // 任务数
    private static final AtomicInteger taskCount = new AtomicInteger(0);

    // 需要停止的任务
    private static final AtomicInteger needStopTaskCount = new AtomicInteger(0);

    private static final CopyOnWriteArraySet<String> taskList = new CopyOnWriteArraySet<>();

    @Scheduled(cron = "0/5 * * * * ?")
    public void monitorCPUUsage() {
        getSystemUsage();
        double cpuUsage = getCpuUsage();
        System.out.printf(LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_PATTERN) + " CPU 使用率: %.2f%%,任务数:%d\n", cpuUsage * 100, taskList.size());

    }

    /**
     * 检查操作系统的CPU使用情况
     */
    @Scheduled(cron = "0/15 * * * * ?")
    public void checkOSHI() {
        System.out.println("开始监控并控制 CPU 使用率...");
        double cpuUsage = getCpuUsage();
        System.out.printf("当前 CPU 使用率: %.2f%%\n", cpuUsage * 100);

        if (cpuUsage < TARGET_CPU_USAGE) {
            // 当前 CPU 使用率太低,增加任务
            startCpuIntensiveTask();
        } else if (cpuUsage > TARGET_CPU_USAGE + 0.2) {
            // 当前 CPU 使用率太高,减少任务
            stopCpuIntensiveTask();
        }
    }


    /**
     * 获取当前 CPU 使用率
     */
    public static double getCpuUsage() {
        SystemInfo systemInfo = new SystemInfo();
        CentralProcessor processor = systemInfo.getHardware().getProcessor();

        long[] prevTicks = processor.getSystemCpuLoadTicks();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return processor.getSystemCpuLoadBetweenTicks(prevTicks);
    }

    /**
     * 启动一个 CPU 密集型任务
     */
    public static void startCpuIntensiveTask() {
        System.out.println("启动一个 CPU 密集型任务");
        if (taskCount.get() >= 100) {   // 限制最大任务数
            return;
        }
        taskCount.incrementAndGet();
        if (needStopTaskCount.get() > 0) {
            needStopTaskCount.decrementAndGet();
            return;
        }

        executor.submit(() -> {
            while (running.get()) {
                if (needStopTaskCount.get() > 0) {
                    needStopTaskCount.decrementAndGet();
                    System.out.println("停止了一个任务");
                    taskList.remove(Thread.currentThread().getName());
                    return;
                }
                taskList.add(Thread.currentThread().getName());
                // 简单的 CPU 密集型计算
                double result = 0;
                for (int i = 0; i < 100000 && running.get(); i++) {
                    result += Math.sqrt(i);
                }
                // 模拟短暂空闲
                // LockSupport.parkNanos(WORK_INTERVAL_NS);
            }
        });
    }

    /**
     * 停止一个任务
     */
    public static void stopCpuIntensiveTask() {
        needStopTaskCount.addAndGet(1);
        if (taskCount.get() > 0) {
            taskCount.decrementAndGet();
        }
        System.out.println("需要停止任务数:" + needStopTaskCount.get());
    }

    /**
     * 停止所有任务(程序退出时调用)
     */
    public static void shutdown() {
        System.out.println("停止所有任务");
        running.set(false);
        executor.shutdown();
    }

    public void getSystemUsage() {
        final long GB = 1024 * 1024 * 1024;
        // while (true) {
            OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
            String osJson = JSON.toJSONString(operatingSystemMXBean);
//            System.out.println("osJson is " + osJson);
            JSONObject jsonObject = JSON.parseObject(osJson);
            double processCpuLoad = jsonObject.getDouble("processCpuLoad") * 100;
            double systemCpuLoad = jsonObject.getDouble("systemCpuLoad") * 100;
            Long totalPhysicalMemorySize = jsonObject.getLong("totalPhysicalMemorySize");
            Long freePhysicalMemorySize = jsonObject.getLong("freePhysicalMemorySize");
            double totalMemory = 1.0 * totalPhysicalMemorySize / GB;
            double freeMemory = 1.0 * freePhysicalMemorySize / GB;
            double memoryUseRatio = 1.0 * (totalPhysicalMemorySize - freePhysicalMemorySize) / totalPhysicalMemorySize * 100;

            StringBuilder result = new StringBuilder();
            result.append("系统CPU占用率: ")
                    .append(twoDecimal(systemCpuLoad))
                    .append("%,内存占用率:")
                    .append(twoDecimal(memoryUseRatio))
                    .append("%,系统总内存:")
                    .append(twoDecimal(totalMemory))
                    .append("GB,系统剩余内存:")
                    .append(twoDecimal(freeMemory))
                    .append("GB,该进程占用CPU:")
                    .append(twoDecimal(processCpuLoad))
                    .append("%");
            System.out.println(result.toString());
    }

    public double twoDecimal(double doubleValue) {
        BigDecimal bigDecimal = new BigDecimal(doubleValue).setScale(2, RoundingMode.HALF_UP);
        return bigDecimal.doubleValue();
    }
}