十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
1、首先dump出该进程的所有线程及状态
创新互联公司坚信:善待客户,将会成为终身客户。我们能坚持多年,是因为我们一直可值得信赖。我们从不忽悠初访客户,我们用心做好本职工作,不忘初心,方得始终。10年网站建设经验创新互联公司是成都老牌网站营销服务商,为您提供成都网站制作、网站设计、外贸网站建设、网站设计、html5、网站制作、品牌网站建设、成都微信小程序服务,给众多知名企业提供过好品质的建站服务。
使用命令 jstack PID 命令打印出CPU占用过高进程的线程栈.
jstack -l56835683.stack
将进程id为5683的线程栈输出到了文件
2、使用top命令找到耗cpu的线程
使用top -H -p PID 命令查看对应进程是哪个线程占用CPU过高.
1、确定当前系统安装的jdk是1.6版本以上
2、windows系统中有获取cpu使用率的可执行文件exe,只要在java中获取该文件的执行路径,通过Java调用即可。
3、获取操作系统可执行文件目录procCmd
4、调用java的Runtime.getRuntime().exec执行cmd应用程序
5、利用java中sleep来计算睡眠前后cpu的忙碌时间与空闲时间,因为sleep不会释放系统资源
6、根据忙碌时间占总时间的比例来计算cpu使用率
示例:
private double getCpuRatioForWindows() {
try {
String procCmd = System.getenv("windir")
+ "//system32//wbem//wmic.exe process get Caption,CommandLine,"
+ "KernelModeTime,ReadOperationCount,ThreadCount,UserModeTime,WriteOperationCount";
// 取进程信息
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核心可以搭载两个线程,你根据核心去搭载线程,不要乱放线程。
还有你有10个线程同时跑耗时操作最少也要4核的cpu,你可以减少线程或者减少线程中的耗时操作。
如果你是解码或者压缩程序的话那么cpu100%也很正常,如果是socket网络连接你可以看看windows iocp,linux epoll的实现。
Java的System.currentTimeMillis()方法可以尝试,思路为计算后时间的时间减去计算前的时间,只能说是尽量接进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的进程Id(PID) 假设java应用名称是zcg_commodity
ps -ef|grep zcg_commodity
得到进程Id为32464
第二步:找出该进程内最消耗CPU的线程
top -Hp pid
输入top -Hp 32464
TIME列就是各个java线程耗费的CPU的时间,比如图中是线程ID的为2012的线程,
通过 printf “%x\n” 2012
得到2012的十六进制为 7dc
第三步:
一般会进到jdk的bin目录下,root权限执行
jstack 32464|grep 7dc
首先有个基本问题需要了解一下:
这里所说java里获得一个进程的内存使用情况和cpu运行时间,是指在java内部获取一个纯外部进程的内存与cpu时间呢,还是指在java内部,由java启动的进程的内存与cpu时间。
如果是第一种情况,那你还需要在java内部再起一个进程,通过执行操作系统的shell命令来查看那个进程的运行状态。比如那个外部进程的ID为3119,则执行cat /proc/3119/status | grep VmRSS就可以过滤出该进程的物理内存占用量。
如果是第二种情况,(假定你问的就是这种情况)。
先说内存占用量:一般说来,你可以使用这两种方式获取内存使用情况
方式一:
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage(); //椎内存使用情况
long totalMemorySize = memoryUsage.getInit(); //初始的总内存
long maxMemorySize = memoryUsage.getMax(); //最大可用内存
long usedMemorySize = memoryUsage.getUsed(); //已使用的内存
方式二:
Runtime rt = Runtime.getRuntime();
long totalMemorySize = rt.totalMemory(); //初始的总内存
long maxMemorySiz = t.maxMemory(); //最大可用内存
long freeMemorySize = rt.freeMemory(); //当前可用内存
需要说明的是,这种方式获取的是整个jvm的内存使用情况,并不是某一个进程的内存使用情况,事实上,在java内部,可以使用Rumtime.getRuntime().exec(${SHELL})来开启一个外部进程(这里${SHELL}代表一个可操作系统的shell命令)。而运行Java程序整个jvm,对于操作系统而言,也仅仅只是一个进程。也就是说,一个jvm就是一个进程,你通过java程序开启的进程都是外部进程,java内部目前还提供了一个destroy方法来销毁该进程,对于该进程的其它信息,都无法直接获取,这些信息的获取,显然需要本地化(Local)的实现。既然标准jdk库没有,就不可能再通过平台无关的代码来实现了。典型的做法就是使用前面第一种情况的方式,再启一个进程,执行shell命令来获取。
不过对于cpu使用时间,采用标准java代码倒是可以拿到。由于java的语法很啰嗦,举一个较完全的例子需要太多的代码,我这里就只写最关键的代码:
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
① long currentCpuTime = threadMXBean.getCurrentThreadCpuTime(); //当前线程的cpu使用时间
long someThreadId = 709817L; //假定有某个线程的ID是709817
② long someThreadCpuTime = threadMXBean.getThreadCpuTime(someThreadId); //获取ID为someThreadId即709817的线程的cpu时间
基于上面的核心api,你可以把由java启动的外部进程放到一个单独的线程中执行,再用代码②的方式来获取该进程的cpu使用时间,也可以将外部进程放入到当前线程中执行,用① 的方式来获得进程的cpu使用时间。