来自 Java 的 CPU 负载
有没有办法在不使用JNI的情况下获得Java下的当前CPU负载?
getSystemLoadAverage() 在 1 分钟的时间内为您提供值(每秒刷新一次),并为整个操作系统提供此值。应通过单独监视每个线程来完成更实时的概述。同样重要的是注意监视刷新间隔 - 更频繁地检查值,更多的是它在给定的时刻,如果您每毫秒这样做一次,它通常是0或100(或更多,具体取决于有多少CPU)。但是,如果我们允许时间帧(例如1秒),我们将在这段时间内获得变化,并且我们得到更翔实的结果。此外,重要的是要注意,只有一个线程占用多个CPU(内核)的可能性极小。
以下实现允许使用 3 种方法:
getUsageByThread(Thread t) - 指定线程的总负载
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadMXBean;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class MonitoringThread extends Thread {
private long refreshInterval;
private boolean stopped;
private Map<Long, ThreadTime> threadTimeMap = new HashMap<Long, ThreadTime>();
private ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
private OperatingSystemMXBean opBean = ManagementFactory.getOperatingSystemMXBean();
public MonitoringThread(long refreshInterval) {
this.refreshInterval = refreshInterval;
setName("MonitoringThread");
start();
}
@Override
public void run() {
while(!stopped) {
Set<Long> mappedIds;
synchronized (threadTimeMap) {
mappedIds = new HashSet<Long>(threadTimeMap.keySet());
}
long[] allThreadIds = threadBean.getAllThreadIds();
removeDeadThreads(mappedIds, allThreadIds);
mapNewThreads(allThreadIds);
Collection<ThreadTime> values;
synchronized (threadTimeMap) {
values = new HashSet<ThreadTime>(threadTimeMap.values());
}
for (ThreadTime threadTime : values) {
synchronized (threadTime) {
threadTime.setCurrent(threadBean.getThreadCpuTime(threadTime.getId()));
}
}
try {
Thread.sleep(refreshInterval);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
for (ThreadTime threadTime : values) {
synchronized (threadTime) {
threadTime.setLast(threadTime.getCurrent());
}
}
}
}
private void mapNewThreads(long[] allThreadIds) {
for (long id : allThreadIds) {
synchronized (threadTimeMap) {
if(!threadTimeMap.containsKey(id))
threadTimeMap.put(id, new ThreadTime(id));
}
}
}
private void removeDeadThreads(Set<Long> mappedIds, long[] allThreadIds) {
outer: for (long id1 : mappedIds) {
for (long id2 : allThreadIds) {
if(id1 == id2)
continue outer;
}
synchronized (threadTimeMap) {
threadTimeMap.remove(id1);
}
}
}
public void stopMonitor() {
this.stopped = true;
}
public double getTotalUsage() {
Collection<ThreadTime> values;
synchronized (threadTimeMap) {
values = new HashSet<ThreadTime>(threadTimeMap.values());
}
double usage = 0D;
for (ThreadTime threadTime : values) {
synchronized (threadTime) {
usage += (threadTime.getCurrent() - threadTime.getLast()) / (refreshInterval * 10000);
}
}
return usage;
}
public double getAvarageUsagePerCPU() {
return getTotalUsage() / opBean.getAvailableProcessors();
}
public double getUsageByThread(Thread t) {
ThreadTime info;
synchronized (threadTimeMap) {
info = threadTimeMap.get(t.getId());
}
double usage = 0D;
if(info != null) {
synchronized (info) {
usage = (info.getCurrent() - info.getLast()) / (refreshInterval * 10000);
}
}
return usage;
}
static class ThreadTime {
private long id;
private long last;
private long current;
public ThreadTime(long id) {
this.id = id;
}
public long getId() {
return id;
}
public long getLast() {
return last;
}
public void setLast(long last) {
this.last = last;
}
public long getCurrent() {
return current;
}
public void setCurrent(long current) {
this.current = current;
}
}
}