diff --git a/src/main/java/com/yexuejc/base/util/SysUtil.java b/src/main/java/com/yexuejc/base/util/SysUtil.java index 4b0758f..83c3b66 100644 --- a/src/main/java/com/yexuejc/base/util/SysUtil.java +++ b/src/main/java/com/yexuejc/base/util/SysUtil.java @@ -3,7 +3,15 @@ package com.yexuejc.base.util; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.net.URL; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; +import java.util.logging.Logger; /** * 系统工具类 @@ -14,6 +22,7 @@ import java.util.concurrent.*; * @date: 2017/12/28 16:12 */ public class SysUtil { + private static Logger logger = Logger.getLogger(SysUtil.class.getName()); private static final String PROJECT_ROOT_PATH = "java.io.tmpdir"; private SysUtil() { @@ -79,4 +88,116 @@ public class SysUtil { */ void execute(); } + + + /** + * 获取当前JVM所有线程 + * + * @return + */ + public static List getThreadList() { + List threadList = new ArrayList<>(); + ThreadGroup currentGroup = Thread.currentThread().getThreadGroup(); + while (currentGroup.getParent() != null) { + currentGroup = currentGroup.getParent(); + } + int activeCount = currentGroup.activeCount(); + Thread[] threads = new Thread[activeCount]; + currentGroup.enumerate(threads); + for (Thread thread : threads) { + threadList.add(thread); + } + return threadList; + } + + /** 线程锁 */ + private static final Lock THREAD_LOCK = new ReentrantLock(); + /** 已经等待的时间 */ + private static final AtomicInteger SLEEP_TIME = new AtomicInteger(0); + /** 最大等待3分钟 */ + private static final int MAX_SLEEP_TIME = 180; + + /** + * 通过锁的方式判断jvm的内存,如果超80%就等待(最大3分钟)JVM内存降低到80%再执行 + */ + public static void checkJvmMemory() { + THREAD_LOCK.lock(); + try { + while (jvmMemoryIsNotExecutable()) { + //jvm内存使用率达到80%,阻塞所有线程,最大等待3分钟后放开 + if (SLEEP_TIME.incrementAndGet() < MAX_SLEEP_TIME) { + TimeUnit.SECONDS.sleep(1); + } else { + break; + } + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + THREAD_LOCK.unlock(); + SLEEP_TIME.set(0); + } + } + + /** + * jvm内存是否大于80%(不能继续执行) + * + * @return true:是,false:不是 + */ + public static boolean jvmMemoryIsNotExecutable() { + Runtime runtime = Runtime.getRuntime(); + //jvm总内存 + long jvmTotalMemoryByte = runtime.totalMemory(); + //jvm最大可申请 + long jvmMaxMemoryByte = runtime.maxMemory(); + //空闲空间 + long freeMemoryByte = runtime.freeMemory(); + + double rate = (jvmTotalMemoryByte - freeMemoryByte) * 1.0 / jvmTotalMemoryByte; + if (rate >= 0.8) { + rate = (jvmTotalMemoryByte - freeMemoryByte) * 1.0 / jvmMaxMemoryByte; + if (rate >= 0.8) { + //jvm内存使用率达到80% + print(jvmTotalMemoryByte, jvmMaxMemoryByte, freeMemoryByte); + return true; + } + } + return false; + } + + private static final DecimalFormat RATE_DECIMAL_FORMAT = new DecimalFormat("#.##%"); + + private static void print(long jvmTotalMemoryByte, long jvmMaxMemoryByte, long freeMemoryByte) { + if (logger.isLoggable(Level.WARNING)) { + String sb = "\n=========================================================" + + "\nThread Name = " + Thread.currentThread().getName() + + "\nJVM Memory = " + formatByte(jvmTotalMemoryByte) + + "\nJVM Max Memory = " + formatByte(jvmMaxMemoryByte) + + "\nJVM Used Memory = " + formatByte(jvmTotalMemoryByte - freeMemoryByte) + + "\nJVM Free Memory = " + formatByte(freeMemoryByte) + + "\nJVM Memory Rate = " + RATE_DECIMAL_FORMAT.format((jvmTotalMemoryByte - freeMemoryByte) * 1.0 / jvmTotalMemoryByte) + + "\n========================================================="; + logger.warning(sb); + } + } + + private static String formatByte(long byteNumber) { + //换算单位 + double format = 1024.0; + double kbNumber = byteNumber / format; + if (kbNumber < format) { + return new DecimalFormat("#.##KB").format(kbNumber); + } + double mbNumber = kbNumber / format; + if (mbNumber < format) { + return new DecimalFormat("#.##MB").format(mbNumber); + } + double gbNumber = mbNumber / format; + if (gbNumber < format) { + return new DecimalFormat("#.##GB").format(gbNumber); + } + double tbNumber = gbNumber / format; + return new DecimalFormat("#.##TB").format(tbNumber); + } + }