云服务器申请下来长期不用避免被回收,通过下面代码可消耗Cpu消耗和内存消耗,让服务器处于一个合理利用的状态,避免闲置回收
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.ref.SoftReference;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
public class MemConsumeListener implements ServletContextListener {
/**
* cpu 阈值 百分比%
*/
private static final int Cpu_LOAD_puTHRESHOLD = 15;
/**
* 内存 阈值 百分比%
*/
private static final int Mem_LOAD_THRESHOLD = 30;
private static volatile boolean shouldRun = true;
private static volatile boolean MenRun = true;
private static OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
// 设定最大内存阈值为JVM最大内存的一半
private static final long MAX_MEMORY_THRESHOLD = Runtime.getRuntime().maxMemory() / 2;
private static final List<SoftReference<byte[]>> memoryPool = new ArrayList<>();
@Override
public void contextInitialized(ServletContextEvent sce) {
// 在这里写入你需要在Tomcat启动时运行的代码
System.out.println("启动运行CPU、内存消耗程序...");
System.out.println("当前JVM内存: "+ MAX_MEMORY_THRESHOLD /(1024 * 1024) + " MB;");
System.out.println("当前内存阈值: "+ Mem_LOAD_THRESHOLD + "%;");
System.out.println("当前CPU阈值: "+ Cpu_LOAD_puTHRESHOLD + "%;");
printInfo();
//消耗cpu
CPUBurner();
try {
// 消耗内存
MemoryManager();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("停止运行Tomcat...");
System.out.println("释放内存");
memoryPool.clear();
System.gc();
}
public static void CPUBurner() {
// 假设这是检查CPU使用率的函数,这里用模拟的sleep代替
Thread checkerThread = new Thread(() -> {
while (true) {
// 模拟CPU检查,假设检查每2秒执行一次
try {
Thread.sleep(500);
if (getCpuUsage() >= Cpu_LOAD_puTHRESHOLD) {
shouldRun = false;
}
else if(!shouldRun){
shouldRun = true;
expendCpu();
}
expendCpu();
} catch (Exception e) {
Thread.currentThread().interrupt();
}
}
});
checkerThread.start();
}
private static void expendCpu(){
// 真正的CPU消耗线程
Thread consumerThread = new Thread(() -> {
while (shouldRun) { // 注意:这个循环实际上永远不会自然停止
for (long j = 0; j < 10; j++) {
double result = Math.sin(j) * Math.cos(j);
}
}
});
consumerThread.start();
}
/**
* 获取cpu使用率
* @return
* @throws Exception
*/
private static double getCpuUsage() throws Exception {
double cpuLoad = 0l;
if (osBean instanceof com.sun.management.OperatingSystemMXBean) {
com.sun.management.OperatingSystemMXBean sunOsBean = (com.sun.management.OperatingSystemMXBean) osBean;
cpuLoad = sunOsBean.getSystemCpuLoad();
if (cpuLoad == -1.0) {
throw new Exception("系统平均负载不可用");
}
}else{
cpuLoad = osBean.getSystemLoadAverage();
if (cpuLoad == -1.0) {
throw new Exception("系统平均负载不可用");
}
}
//System.out.println("系统平均负载:" + cpuLoad *100);
return cpuLoad * 100;
}
public static void MemoryManager() throws InterruptedException {
Runtime runtime = Runtime.getRuntime();
while (true) {
long freeMemory = runtime.freeMemory();
long totalMemory = runtime.totalMemory();
long usedMemory = totalMemory - freeMemory;
// System.out.print("Total Memory: " + totalMemory / (1024 * 1024) + " MB;");
// System.out.print("Free Memory: " + freeMemory / (1024 * 1024) + " MB;");
// System.out.println("Used Memory: " + usedMemory / (1024 * 1024) + " MB;");
//这边的限制是避免当前运行程序嘎掉
if (usedMemory < MAX_MEMORY_THRESHOLD && MenRun) {
// 消耗内存
consumeMemory();
}
// else {
// // 尝试“释放”内存(通过减少引用)
// releaseMemory();
// // 注意:这里并没有直接释放内存,只是减少了对象引用,让JVM有机会回收这些对象
// // 调用System.gc()请求JVM进行垃圾回收,但JVM可以忽略这个请求
// System.gc();
// }
// 暂停一段时间以便观察效果
Thread.sleep(1000);
}
}
private static void consumeMemory() {
byte[] data = new byte[1024 * 1024 * 10]; // 100MB数据 104857600
memoryPool.add(new SoftReference<>(data)); // 使用软引用,以便在内存紧张时可以被回收
}
private static void releaseMemory() {
if(memoryPool.size() > 0){
//依次移除memoryPool中的每个对象
memoryPool.remove(0).clear();
}
// 移除引用,让JVM有机会回收这些对象
// memoryPool.clear();
}
private static void printInfo(){
Thread consumerThread = new Thread(() -> {
testSystemUsage();
});
consumerThread.start();
}
public static void testSystemUsage() {
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());
if(((totalMemory - freeMemory)/totalMemory) * 100 > Mem_LOAD_THRESHOLD){
//内存空余率小于0.7 释放内存
MenRun = false;
releaseMemory();
System.gc();
}else{
MenRun = true;
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static double twoDecimal(double doubleValue) {
BigDecimal bigDecimal = new BigDecimal(doubleValue).setScale(2, RoundingMode.HALF_UP);
return bigDecimal.doubleValue();
}
}