Java计算cpu利用率_java得到机器cpu使用率的计算方法深入理解

文章目录

之前写熔断功能,需要获取机器的cpu使用率

从/proc文件系统获取cpu使用情况: cat /proc/stat

输出解释:

idle (422145968) 从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间(单位:jiffies)

得到:

CPU利用率 = 1- (idle2-idle1)/(cpu2-cpu1)

这里的idle1、idle2是从 开机到现在 的cpu空闲时间,cpu1、cpu2是从开机到现在的总的时间

一个同事说,这样违背了需求,不是瞬时的cpu的值

举个栗子

Java计算cpu利用率_java得到机器cpu使用率的计算方法深入理解_第1张图片

假如我凌晨0点开始,现在是24小时后的凌晨0点,在这一天中,0点到1点我都开吭哧吭哧的干活,早早干完了,1点到24点,坐着嗑瓜子,如果算瞬时的cpu使用率,岂不是要 1/24 ,可是这能表示我当前的cpu吗?

注意cpu的单位是时间

所以就出现了上面的公式

CPU利用率 = 1- (idle2-idle1)/(cpu2-cpu1)

而我们两次采集的时间间隔尽可能的小,就确保了尽可能的求瞬时的值,但是不能到达真正的瞬时。

其实按照正常的思维,用开始到现在使用的时间除以开始到现在总的时间,看似是瞬时的,实际上可以吧开始那个瞬间看做是一次采集,当前时间是一次采集,即相当于将上面的公式的采集时间拉长了,本质上没什么区别,反而精度下降了不是一点点。

通过将时间间隔缩小确实能够达到目的,但是不能小于Jiffies,什么是Jiffies,看下面我摘录的一段话:

在Linux的内核中,有一个全 局变量:Jiffies。

Jiffies代表时间。它的单位随硬件平台的不同而不同。系统里定义了一个常数HZ,代表每秒种最小时间间隔的数目。这样jiffies的单位就是

1/HZ。Intel平台jiffies的单位是1/100秒,这就是系统所能分辨的最小时间间隔了。每个CPU时间片,Jiffies都要加1。

CPU的利用率就是用执行用户态+系统态的Jiffies除以总的Jifffies来表示。

在Linux内核中,每个进程都会被分配一个固定的时间片,默认为10ms,在这10ms中,该进程享有cpu的所有权。10ms看上去很短,但以2.6GHz的Intel处理器为例,10ms能够处理5000w条指令,对于绝大多数的应用这已经足够长了。如果该进程用完了10ms,或者有其他优先级高的进程发出请求,系统会触发一个中断,内核重新接管cpu,内核分配cpu给其他进程。10ms的分片让用户,也就是我们觉得我们的系统运转非常流畅,尽管我们可能同时开了很多的应用。

Jiffies

我们或许会对10ms的分片感到疑惑,为什么是10ms?可不可以是其他值?答案是肯定的,但无论它被设定为多少,它只是指示了内核以一个怎样的时间间隔重新接管cpu。内核接管了cpu后,可能会干一些琐碎的事,其中有一件就是累加一个变量,也就是Jiffies。这样一来,每隔10ms,Jiffies就要加1,Jiffies指示了从开机以来经过了多少个10ms.HZ

和我们平常所知的Hz不一样,这里的HZ是Linux系统定义的一个常数,代表了每秒钟最小时间间隔的数目,它有默认值为100。这样Jiffies的单位就是1/HZ,即1/100秒,这是系统所能分辨的最小时间间隔了。

参考:https://www.2cto.com/kf/201708/666530.html

当然还有很多java代码获取机器cpu使用率的方式,没必要纠结于这一种。

java代码

/**

* 采集CPU使用率

*/

public class CpuUsage extends ResourceUsage {

private static Logger log = Logger.getLogger(CpuUsage.class);

private static CpuUsage INSTANCE = new CpuUsage();

private CpuUsage(){

}

public static CpuUsage getInstance(){

return INSTANCE;

}

/**

* Purpose:采集CPU使用率

* @param args

* @return float,CPU使用率,小于1

*/

@Override

public float get() {

log.info("开始收集cpu使用率");

float cpuUsage = 0;

Process pro1,pro2;

Runtime r = Runtime.getRuntime();

try {

String command = "cat /proc/stat";

//第一次采集CPU时间

long startTime = System.currentTimeMillis();

pro1 = r.exec(command);

BufferedReader in1 = new BufferedReader(new InputStreamReader(pro1.getInputStream()));

String line = null;

long idleCpuTime1 = 0, totalCpuTime1 = 0; //分别为系统启动后空闲的CPU时间和总的CPU时间

while((line=in1.readLine()) != null){

if(line.startsWith("cpu")){

line = line.trim();

log.info(line);

String[] temp = line.split("\\s+");

idleCpuTime1 = Long.parseLong(temp[4]);

for(String s : temp){

if(!s.equals("cpu")){

totalCpuTime1 += Long.parseLong(s);

}

}

log.info("IdleCpuTime: " + idleCpuTime1 + ", " + "TotalCpuTime" + totalCpuTime1);

break;

}

}

in1.close();

pro1.destroy();

try {

Thread.sleep(100);

} catch (InterruptedException e) {

StringWriter sw = new StringWriter();

e.printStackTrace(new PrintWriter(sw));

log.error("CpuUsage休眠时发生InterruptedException. " + e.getMessage());

log.error(sw.toString());

}

//第二次采集CPU时间

long endTime = System.currentTimeMillis();

pro2 = r.exec(command);

BufferedReader in2 = new BufferedReader(new InputStreamReader(pro2.getInputStream()));

long idleCpuTime2 = 0, totalCpuTime2 = 0; //分别为系统启动后空闲的CPU时间和总的CPU时间

while((line=in2.readLine()) != null){

if(line.startsWith("cpu")){

line = line.trim();

log.info(line);

String[] temp = line.split("\\s+");

idleCpuTime2 = Long.parseLong(temp[4]);

for(String s : temp){

if(!s.equals("cpu")){

totalCpuTime2 += Long.parseLong(s);

}

}

log.info("IdleCpuTime: " + idleCpuTime2 + ", " + "TotalCpuTime" + totalCpuTime2);

break;

}

}

if(idleCpuTime1 != 0 && totalCpuTime1 !=0 && idleCpuTime2 != 0 && totalCpuTime2 !=0){

cpuUsage = 1 - (float)(idleCpuTime2 - idleCpuTime1)/(float)(totalCpuTime2 - totalCpuTime1);

log.info("本节点CPU使用率为: " + cpuUsage);

}

in2.close();

pro2.destroy();

} catch (IOException e) {

StringWriter sw = new StringWriter();

e.printStackTrace(new PrintWriter(sw));

log.error("CpuUsage发生InstantiationException. " + e.getMessage());

log.error(sw.toString());

}

return cpuUsage;

}

/**

* @param args

* @throws InterruptedException

*/

public static void main(String[] args) throws InterruptedException {

while(true){

System.out.println(CpuUsage.getInstance().get());

Thread.sleep(5000);

}

}

}

转载过一篇文章:https://blog.csdn.net/dataiyangu/article/details/83988775

你可能感兴趣的:(Java计算cpu利用率)