1. 程式人生 > >java程式中執行緒cpu使用率計算

java程式中執行緒cpu使用率計算

原文地址:https://www.imooc.com/article/27374

最近確實遇到題目上的剛需,也是花了一段時間來思考這個問題。

cpu使用率如何計算

    計算使用率在上學那會就經常算,不過往往計算的是整個程式執行的時間段,現在突然要實時計算還真有點無奈,時間段如何選擇是個問題。最後根據現有的程式做參考,那就是Linux的top命令原始碼。

    top命令還是c程式,加之開源,我直接採取相同的時間段和計算方法。

    先說說top是如何計算的,首先是從/proc/stat下讀取cpu的使用時間,其次就是/proc/pid/stat獲取程序的cpu時間,/proc/pid/task裡獲取這個程序裡每個執行緒的id,然後繼續從stat裡查詢cpu的使用時間。

    執行緒cpu的利用率=執行緒執行的時間差(包括使用者態+核心態+。。。。)/cpu執行時間之差(使用者態+核心態+io+.....)

    每隔3秒查詢計算一次。

java實現過程

    既然要獲取cpu資訊,我查詢了很多方法,最終確定,java本身是做不到的(windows可沒有/proc這樣的檔案給你檢視),要藉助c/c++來處理,原本我呼叫函式都查好了,就差寫jni了,結果有人給我推薦了sigar。是就是基於本地庫實現的,不過他已經把本地庫這些都準備好了,基本每個平臺都有,這樣提供了很大的方便。接下來就是對這個庫的使用過程了。

    根據給出的參考例子和相關api文件。我們匯入Jar包後需要繼承SigarCommandBase這個類,我們一切的操作基本依靠父類的成員變數sigar

    Cpu[] cpus = this.sigar.getCpuList();//獲取cpu資訊
    long time = 0L;
    for (int i = 0; i < cpus.length; i++) {
      time += cpus[i].getTotal();
    }
    return time;

    先獲取到cpu的資訊,然後直接通過getTotal來得到當前cpu的執行時間,你可以用cpus獲取到cpu在核心態執行時間等等,我最後嘗試加起來和getTotal小有出入,差別不大,所以採用getTotal就可以了,這樣就能獲取cpu執行時間,第二次採集時也就知道時間差了。

    接下來就是獲取java執行緒資訊這些了,依然還是算差值。

   ThreadMXBean mx = ManagementFactory.getThreadMXBean();
    long[] threadIds = mx.getAllThreadIds();
    ThreadInfo[] threadInfos = mx.getThreadInfo(threadIds);

    通過上面的程式碼就可以獲取到現在程序裡每個執行緒的資訊。

  long time = mx.getThreadCpuTime(threadId);

    再通過getThreadCpuTime方法根據tid來獲取到該執行緒在cpu上執行總時間,java文件上是這麼寫的:返回指定 ID 的執行緒的總 CPU 時間(以毫微秒為單位)。這裡的單位是毫微秒的單位,要注意轉換。

    我儲存執行緒資訊是用一個map,主鍵是執行緒id,這裡大家就需要稍微注意一下,我更建議是執行緒id+執行緒名字的手段來做主鍵,tid是標識唯一一個執行緒,我們假設a執行緒的id是34,如果a執行緒死掉之後,b執行緒啟動,jvm會不會把34號標識給b執行緒呢,這裡我不敢肯定,我感覺是會的。在linux的檔案描述符也是唯一標識一個檔案的,但是你一個檔案關閉後,再開一個,肯定會佔用到相同的描述符。所以我感覺執行緒的id也是如此,id是標識了唯一的執行緒,但是執行緒死掉,重新分配的話,這樣也程式碼不必要的困擾。

    剩下的就是算差值來計算使用率了,記得把動態庫的位置加上,-Djava.library.path="位置",windows下可以加到path路徑下,linux可以指定LD_LIBARARY_PATH。