有没有办法在不使用JNI的情况下在Java下获取当前的cpu负载?
答案 0 :(得分:25)
答案 1 :(得分:5)
这确实涉及JNI,但是有一个名为Sigar的Hyperic的GPL库,它为所有主要平台提供此信息,以及一些其他依赖于操作系统的统计信息,如磁盘使用情况。它对我们很有用。
答案 2 :(得分:5)
getSystemLoadAverage()为您提供超过1分钟的值(每秒刷新一次),并为整个操作系统提供此值。应通过分别监视每个线程来完成更多实时概述。重要的是还要注意监视刷新间隔 - 更常见的是检查值,在给定时刻更准确,如果每毫秒执行一次,通常为0或100(或更多,具体取决于CPU的数量)。但是如果我们允许时间范围(例如1秒),我们会在这段时间内得到平均值,并获得更多信息。此外,重要的是要注意,极不可能只有一个线程占用多个CPU(核心)。
以下实现允许使用3种方法:
getUsageByThread(线程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;
}
}
}
答案 3 :(得分:2)
在linux上你可以只读取文件/ proc / loadavg,其中前三个值代表负载平均值。对于Windows,您可能必须坚持使用JNI。
答案 4 :(得分:1)
答案 5 :(得分:0)
如果您使用的是JRockit JVM,则可以使用JMAPI。它适用于JDK 1.4,1.5和1.6。
System.out.println("Total CPU-usage:" + JVMFactory.getJVM().getMachine().getCPULoad());
System.out.println("Total JVM-load :" + JVMFactory.getJVM().getJVMLoad());
for(Iterator it = JVMFactory.getJVM().getMachine().getCPUs().iterator(); it.hasNext();)
{
CPU cpu = (CPU)it.next();
System.out.println("CPU Description: " + cpu.getDescription());
System.out.println("CPU Clock Frequency: " + cpu.getClockFrequency());
System.out.println("CPU Load: " + cpu.getLoad());
System.out.println();
}