getSystemLoadAverage () дает вам значение за 1 минуту времени (обновляется каждую секунду) и дает это значение для всей операционной системы. Более подробный обзор в реальном времени должен быть сделан путем мониторинга каждого потока в отдельности. Важно также обратить внимание на интервал обновления мониторинга - чаще вы проверяете значение, тем точнее оно находится в данный момент, и если вы делаете это каждую миллисекунду, оно обычно равно 0 или 100 (или больше, в зависимости от количества процессоров). Но если мы допустим таймфрейм (например, 1 секунду), мы получаем среднее значение за этот период времени и получаем более информативный результат. Также важно отметить, что маловероятно, что только один поток занимает более одного ЦП (ядра).
Следующая реализация позволяет использовать 3 метода:
- getTotalUsage () - Общая загрузка всех потоков в JVM
- getAvarageUsagePerCPU () - средняя нагрузка на процессор (ядро)
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;
}
}
}