来自Java的CPU负载

paw*_*que 18 java profiling

有没有办法在不使用JNI的情况下获取Java下的当前cpu负载?

Kai*_*lda 6

getSystemLoadAverage()为您提供超过1分钟的值(每秒刷新)并为整个操作系统提供此值.应通过分别监视每个线程来完成更多实时概述.重要的是还要注意监视刷新间隔 - 通常检查值,在给定时刻更准确,如果每毫秒执行一次,则通常为0或100(或者更多,具体取决于CPU的数量).但是如果我们允许时间范围(例如1秒),我们会在这段时间内得到平均值,并获得更多信息.此外,重要的是要注意,极不可能只有一个线程占用多个CPU(核心).

以下实现允许使用3种方法:

  • getTotalUsage() - JVM中所有线程的总负载
  • getAvarageUsagePerCPU() - 每个CPU(核心)的Avarage负载
  • 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;
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)


Ale*_*ler 5

这确实涉及JNI,但Hyperic中有一个名为Sigar的GPL库,它为所有主要平台提供此信息,以及一些其他依赖于操作系统的统计信息,如磁盘使用情况.它对我们很有用.