十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
1、首先dump出該進(jìn)程的所有線程及狀態(tài)
創(chuàng)新互聯(lián)公司堅信:善待客戶,將會成為終身客戶。我們能堅持多年,是因為我們一直可值得信賴。我們從不忽悠初訪客戶,我們用心做好本職工作,不忘初心,方得始終。10年網(wǎng)站建設(shè)經(jīng)驗創(chuàng)新互聯(lián)公司是成都老牌網(wǎng)站營銷服務(wù)商,為您提供成都網(wǎng)站制作、網(wǎng)站設(shè)計、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站設(shè)計、html5、網(wǎng)站制作、品牌網(wǎng)站建設(shè)、成都微信小程序服務(wù),給眾多知名企業(yè)提供過好品質(zhì)的建站服務(wù)。
使用命令 jstack PID 命令打印出CPU占用過高進(jìn)程的線程棧.
jstack -l56835683.stack
將進(jìn)程id為5683的線程棧輸出到了文件
2、使用top命令找到耗cpu的線程
使用top -H -p PID 命令查看對應(yīng)進(jìn)程是哪個線程占用CPU過高.
1、確定當(dāng)前系統(tǒng)安裝的jdk是1.6版本以上
2、windows系統(tǒng)中有獲取cpu使用率的可執(zhí)行文件exe,只要在java中獲取該文件的執(zhí)行路徑,通過Java調(diào)用即可。
3、獲取操作系統(tǒng)可執(zhí)行文件目錄procCmd
4、調(diào)用java的Runtime.getRuntime().exec執(zhí)行cmd應(yīng)用程序
5、利用java中sleep來計算睡眠前后cpu的忙碌時間與空閑時間,因為sleep不會釋放系統(tǒng)資源
6、根據(jù)忙碌時間占總時間的比例來計算cpu使用率
示例:
private?double?getCpuRatioForWindows()?{??
try?{??
String?procCmd?=?System.getenv("windir")??
+?"http://system32//wbem//wmic.exe?process?get?Caption,CommandLine,"??
+?"KernelModeTime,ReadOperationCount,ThreadCount,UserModeTime,WriteOperationCount";??
//?取進(jìn)程信息??
long[]?c0?=?readCpu(Runtime.getRuntime().exec(procCmd));??
Thread.sleep(CPUTIME);??
long[]?c1?=?readCpu(Runtime.getRuntime().exec(procCmd));??
if?(c0?!=?null??c1?!=?null)?{??
long?idletime?=?c1[0]?-?c0[0];??
long?busytime?=?c1[1]?-?c0[1];??
return?Double.valueOf(??
PERCENT?*?(busytime)?/?(busytime?+?idletime))??
.doubleValue();??
}?else?{??
return?0.0;??
}??
}?catch?(Exception?ex)?{??
ex.printStackTrace();??
return?0.0;??
}??
}
一般一個cpu核心可以搭載兩個線程,你根據(jù)核心去搭載線程,不要亂放線程。
還有你有10個線程同時跑耗時操作最少也要4核的cpu,你可以減少線程或者減少線程中的耗時操作。
如果你是解碼或者壓縮程序的話那么cpu100%也很正常,如果是socket網(wǎng)絡(luò)連接你可以看看windows iocp,linux epoll的實現(xiàn)。
Java的System.currentTimeMillis()方法可以嘗試,思路為計算后時間的時間減去計算前的時間,只能說是盡量接進(jìn)CPU的計算時間
示例如下:
import?java.text.SimpleDateFormat;
import?java.util.Date;
public?class?A{
public?static?void?main(String[]?args)?throws?Exception?{
long?s?=?System.currentTimeMillis();
for?(int?i?=?0;?i??5;?i++)?{
Thread.sleep(5);
}
long?e?=?System.currentTimeMillis();
System.out.println("耗時時間為"?+?(e?-?s)?+?"毫秒");
}
}
第一步:先找出java的進(jìn)程Id(PID) 假設(shè)java應(yīng)用名稱是zcg_commodity
ps -ef|grep zcg_commodity
得到進(jìn)程Id為32464
第二步:找出該進(jìn)程內(nèi)最消耗CPU的線程
top -Hp pid
輸入top -Hp 32464
TIME列就是各個java線程耗費(fèi)的CPU的時間,比如圖中是線程ID的為2012的線程,
通過 printf “%x\n” 2012
得到2012的十六進(jìn)制為 7dc
第三步:
一般會進(jìn)到j(luò)dk的bin目錄下,root權(quán)限執(zhí)行
jstack 32464|grep 7dc
首先有個基本問題需要了解一下:
這里所說java里獲得一個進(jìn)程的內(nèi)存使用情況和cpu運(yùn)行時間,是指在java內(nèi)部獲取一個純外部進(jìn)程的內(nèi)存與cpu時間呢,還是指在java內(nèi)部,由java啟動的進(jìn)程的內(nèi)存與cpu時間。
如果是第一種情況,那你還需要在java內(nèi)部再起一個進(jìn)程,通過執(zhí)行操作系統(tǒng)的shell命令來查看那個進(jìn)程的運(yùn)行狀態(tài)。比如那個外部進(jìn)程的ID為3119,則執(zhí)行cat /proc/3119/status | grep VmRSS就可以過濾出該進(jìn)程的物理內(nèi)存占用量。
如果是第二種情況,(假定你問的就是這種情況)。
先說內(nèi)存占用量:一般說來,你可以使用這兩種方式獲取內(nèi)存使用情況
方式一:
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage(); //椎內(nèi)存使用情況
long totalMemorySize = memoryUsage.getInit(); //初始的總內(nèi)存
long maxMemorySize = memoryUsage.getMax(); //最大可用內(nèi)存
long usedMemorySize = memoryUsage.getUsed(); //已使用的內(nèi)存
方式二:
Runtime rt = Runtime.getRuntime();
long totalMemorySize = rt.totalMemory(); //初始的總內(nèi)存
long maxMemorySiz = t.maxMemory(); //最大可用內(nèi)存
long freeMemorySize = rt.freeMemory(); //當(dāng)前可用內(nèi)存
需要說明的是,這種方式獲取的是整個jvm的內(nèi)存使用情況,并不是某一個進(jìn)程的內(nèi)存使用情況,事實上,在java內(nèi)部,可以使用Rumtime.getRuntime().exec(${SHELL})來開啟一個外部進(jìn)程(這里${SHELL}代表一個可操作系統(tǒng)的shell命令)。而運(yùn)行Java程序整個jvm,對于操作系統(tǒng)而言,也僅僅只是一個進(jìn)程。也就是說,一個jvm就是一個進(jìn)程,你通過java程序開啟的進(jìn)程都是外部進(jìn)程,java內(nèi)部目前還提供了一個destroy方法來銷毀該進(jìn)程,對于該進(jìn)程的其它信息,都無法直接獲取,這些信息的獲取,顯然需要本地化(Local)的實現(xiàn)。既然標(biāo)準(zhǔn)jdk庫沒有,就不可能再通過平臺無關(guān)的代碼來實現(xiàn)了。典型的做法就是使用前面第一種情況的方式,再啟一個進(jìn)程,執(zhí)行shell命令來獲取。
不過對于cpu使用時間,采用標(biāo)準(zhǔn)java代碼倒是可以拿到。由于java的語法很啰嗦,舉一個較完全的例子需要太多的代碼,我這里就只寫最關(guān)鍵的代碼:
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
① long currentCpuTime = threadMXBean.getCurrentThreadCpuTime(); //當(dāng)前線程的cpu使用時間
long someThreadId = 709817L; //假定有某個線程的ID是709817
② long someThreadCpuTime = threadMXBean.getThreadCpuTime(someThreadId); //獲取ID為someThreadId即709817的線程的cpu時間
基于上面的核心api,你可以把由java啟動的外部進(jìn)程放到一個單獨(dú)的線程中執(zhí)行,再用代碼②的方式來獲取該進(jìn)程的cpu使用時間,也可以將外部進(jìn)程放入到當(dāng)前線程中執(zhí)行,用① 的方式來獲得進(jìn)程的cpu使用時間。