调整java占用cpu_调试Java程序持续占cpu问题

1、先用top查看占用cpu的进程id: 20232 114.4%

$ top

top - 09:51:59 up 656 days, 28 min, 3 users, load average: 1.47, 1.56, 1.56

Tasks: 137 total, 1 running, 136 sleeping, 0 stopped, 0 zombie

Cpu(s): 22.8%us, 30.8%sy, 0.0%ni, 45.7%id, 0.3%wa, 0.2%hi, 0.2%si, 0.0%st

Mem: 16331116k total, 12178884k used, 4152232k free, 322252k buffers

Swap: 0k total, 0k used, 0k free, 5134368k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

20232 admin 20 0 3576m 1.1g 14m S 114.4 6.9 883:55.78 java

27380 root 10 -10 129m 18m 5968 S 0.7 0.1 618:38.25 AliYunDun

875 root 20 0 2443m 62m 3416 S 0.3 0.4 15582:24 java

13589 admin 20 0 2825m 1.2g 6496 S 0.3 7.6 457:48.99 java

25834 admin 20 0 1039m 127m 5680 S 0.3 0.8 482:15.84 node /opt/web/d

1 root 20 0 19232 1344 1060 S 0.0 0.0 0:38.92 init

2、再用ps -ef | grep PID定位具体的进程主体;

$ ps -ef|grep activemq

admin 1123 20302 0 09:52 pts/1 00:00:00 grep activemq

admin 20232 1 90 Apr01 pts/0 14:44:25 /opt/jdk1.7.0_71/bin/java -Xms1G -Xmx2G -Djava.util.logging.config.file=logging.properties -Djava.security.auth.login.config=/opt/activemq-5.10.0/conf/login.config -Dcom.sun.management.jmxremote -Djava.awt.headless=true -Djava.io.tmpdir=/opt/activemq-5.10.0/tmp -Dactivemq.classpath=/opt/activemq-5.10.0/conf; -Dactivemq.home=/opt/activemq-5.10.0 -Dactivemq.base=/opt/activemq-5.10.0 -Dactivemq.conf=/opt/activemq-5.10.0/conf -Dactivemq.data=/opt/activemq-5.10.0/data -jar /opt/activemq-5.10.0/bin/activemq.jar start

3、用ps -mp pid -o THREAD,tid,time打印出该进程下的线程占用cpu情况: ps -mp 20232 -o THREAD,tid,time

找到了耗时最高的线程20326,占用CPU时间6个小时了!

$ ps -mp 20232 -o THREAD,tid,time

USER %CPU PRI SCNT WCHAN USER SYSTEM TID TIME

admin 90.5 - - - - - - 14:53:21

admin 40.4 19 - - - - 20326 06:38:38

admin 0.0 19 - futex_ - - 20328 00:00:03

admin 10.6 19 - futex_ - - 1204 00:00:22

admin 0.0 19 - futex_ - - 1208 00:00:00

admin 12.4 19 - futex_ - - 1209 00:00:25

admin 11.7 19 - futex_ - - 1242 00:00:11

admin 0.0 19 - futex_ - - 1252 00:00:00

admin 13.0 19 - futex_ - - 1258 00:00:04

admin 16.4 19 - futex_ - - 1259 00:00:05

admin 0.0 19 - futex_ - - 1287 00:00:00

4、其次将需要的线程ID转换为16进制格式:printf "%x\n" tid

$ printf "%x\n" 20326

4f66

5、最后打印线程的堆栈信息:jstack pid | grep tid -A 30

找到出现问题的代码,并分析具体函数中是否有可能出现死循环的代码段。

通常问题出现在while, for之类的循环代码片段。

$ whereis jstack

jstack: /opt/jdk1.7.0_71/bin/jstack

$ /opt/jdk1.7.0_71/bin/jstack 20232 | grep 4f66 -A 30

"Selector Worker: 0" daemon prio=10 tid=0x00007f84745c5800 nid=0x4f66 runnable [0x00007f845c57e000]

java.lang.Thread.State: RUNNABLE

at sun.misc.Unsafe.unpark(Native Method)

at java.util.concurrent.locks.LockSupport.unpark(LockSupport.java:152)

at java.util.concurrent.SynchronousQueue$TransferStack$SNode.tryMatch(SynchronousQueue.java:263)

at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:380)

at java.util.concurrent.SynchronousQueue.offer(SynchronousQueue.java:914)

at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1364)

at org.apache.activemq.transport.nio.SelectorWorker.run(SelectorWorker.java:116)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

at java.lang.Thread.run(Thread.java:745)

"qtp2033591567-3539 Acceptor0 SelectChannelConnector@0.0.0.0:8161" prio=10 tid=0x00007f8474beb000 nid=0x4f3b runnable [0x00007f845d089000]

java.lang.Thread.State: RUNNABLE

at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)

at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:241)

- locked <0x000000079175fbf8> (a java.lang.Object)

at org.eclipse.jetty.server.nio.SelectChannelConnector.accept(SelectChannelConnector.java:109)

at org.eclipse.jetty.server.AbstractConnector$Acceptor.run(AbstractConnector.java:938)

at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)

at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)

at java.lang.Thread.run(Thread.java:745)

"qtp2033591567-3538 Selector0" prio=10 tid=0x00007f84746cb800 nid=0x4f3a runnable [0x00007f845d18a000]

java.lang.Thread.State: RUNNABLE

at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)

at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)

at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)

at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)

- locked <0x000000079175ffb0> (a sun.nio.ch.Util$2)

$ /opt/jdk1.7.0_71/bin/jstack -F 32215 | grep 7dd7 -A 30

jstack command not found on centos

# sudo updatedb

# locate jstack

/usr/java/jdk1.7.0_79/bin/jstack

/usr/java/jdk1.7.0_79/man/ja_JP.UTF-8/man1/jstack.1

/usr/java/jdk1.7.0_79/man/man1/jstack.1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会给你解答这个问题,但是需要提醒你,由于回答篇幅较长,可能无法在这个对话框内完全呈现,建议你在阅读时开启浏览器并最大化窗口。 首先,我来解释一下什么是进程调度。进程调度是指操作系统决定哪些进程占用CPU,从而实现多个进程同时运行的过程。而基于优先权的进程调度算法和基于时间片轮转调度算法是两种常见的进程调度算法。 基于优先权的进程调度算法是根据进程的优先级来选择下一个要执行的进程。每个进程都有一个优先级,优先级越高的进程越先被执行。如果有多个进程的优先级相同,则可以采用先来先服务(FCFS)的方式进行调度。 基于时间片轮转调度算法是将所有进程按照到达时间的先后顺序排列,并将它们放入一个就绪队列中。操作系统按照一定的时间片轮转,每个进程被分配一个时间片来运行。当一个进程用完了它的时间片,操作系统将它放回就绪队列的末尾,并将下一个进程从队列的头部开始运行。 下面是 Java 实现基于优先权的进程调度算法和基于时间片轮转调度算法的代码示例: 基于优先权的进程调度算法: ```java import java.util.*; public class PriorityScheduling { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n, bt[], wt[], tat[], p[], pr[]; System.out.print("Enter the number of processes: "); n = scanner.nextInt(); bt = new int[n]; wt = new int[n]; tat = new int[n]; p = new int[n]; pr = new int[n]; System.out.println("Enter burst time and priority for each process: "); for (int i = 0; i < n; i++) { System.out.print("Process " + (i + 1) + ": "); bt[i] = scanner.nextInt(); pr[i] = scanner.nextInt(); p[i] = i + 1; } for (int i = 0; i < n - 1; i++) { for (int j = i + 1; j < n; j++) { if (pr[i] < pr[j]) { int temp = pr[i]; pr[i] = pr[j]; pr[j] = temp; temp = bt[i]; bt[i] = bt[j]; bt[j] = temp; temp = p[i]; p[i] = p[j]; p[j] = temp; } } } wt[0] = 0; tat[0] = bt[0]; for (int i = 1; i < n; i++) { wt[i] = wt[i - 1] + bt[i - 1]; tat[i] = tat[i - 1] + bt[i]; } float avg_wt = 0, avg_tat = 0; System.out.println("Process\tBurst Time\tPriority\tWaiting Time\tTurnaround Time"); for (int i = 0; i < n; i++) { avg_wt += wt[i]; avg_tat += tat[i]; System.out.println(p[i] + "\t\t" + bt[i] + "\t\t" + pr[i] + "\t\t" + wt[i] + "\t\t" + tat[i]); } avg_wt /= n; avg_tat /= n; System.out.println("Average Waiting Time: " + avg_wt); System.out.println("Average Turnaround Time: " + avg_tat); } } ``` 基于时间片轮转调度算法: ```java import java.util.*; public class RoundRobinScheduling { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n, bt[], wt[], tat[], p[], ts; System.out.print("Enter the number of processes: "); n = scanner.nextInt(); bt = new int[n]; wt = new int[n]; tat = new int[n]; p = new int[n]; System.out.print("Enter time slice: "); ts = scanner.nextInt(); System.out.println("Enter burst time for each process: "); for (int i = 0; i < n; i++) { System.out.print("Process " + (i + 1) + ": "); bt[i] = scanner.nextInt(); p[i] = i + 1; } int temp[] = new int[n]; for (int i = 0; i < n; i++) { temp[i] = bt[i]; } int t = 0, i = 0; while (true) { boolean flag = true; for (int j = 0; j < n; j++) { if (temp[j] > 0) { flag = false; if (temp[j] > ts) { t += ts; temp[j] -= ts; } else { t += temp[j]; wt[j] = t - bt[j]; temp[j] = 0; } } } if (flag) { break; } } for (int j = 0; j < n; j++) { tat[j] = bt[j] + wt[j]; } float avg_wt = 0, avg_tat = 0; System.out.println("Process\tBurst Time\tWaiting Time\tTurnaround Time"); for (int j = 0; j < n; j++) { avg_wt += wt[j]; avg_tat += tat[j]; System.out.println(p[j] + "\t\t" + bt[j] + "\t\t" + wt[j] + "\t\t" + tat[j]); } avg_wt /= n; avg_tat /= n; System.out.println("Average Waiting Time: " + avg_wt); System.out.println("Average Turnaround Time: " + avg_tat); } } ``` 这些代码示例可以帮助你理解基于优先权的进程调度算法和基于时间片轮转调度算法的实现方法。同时,你还需要了解 Java 编程语言的基本语法和操作系统的相关知识,才能够更好地理解和运用这些代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值