Загрузка процессора с Java
Есть ли способ получить текущую загрузку процессора под Java без использования JNI?
6 ответов
Использовать ManagementFactory
чтобы получить OperatingSystemMXBean
и позвонить getSystemLoadAverage()
в теме.
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; } } }
Это действительно касается JNI, но есть библиотека GPL от Hyperic под названием Sigar, которая предоставляет эту информацию для всех основных платформ, а также множество других зависящих от ОС статистических данных, таких как использование диска. Это отлично сработало для нас.
В Linux вы можете просто прочитать файл /proc/loadavg, где первые три значения представляют средние значения загрузки. Для Windows вы, вероятно, должны придерживаться JNI.
Если вы используете 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();
}