b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

终极:“死亡问题第3章”-如何快速定位无限循环

电脑杂谈  发布时间:2020-09-13 20:02:26  来源:网络整理

如何定位死循环或高cpu使用率(linux)_循环定位软件有什么_linux内核占用cpu高

项目发布后,发现机器的cpu飙升并且负载增加。在故障排除过程中,想到的第一件事应该是研究死锁和循环。死锁和死循环都会导致CPU激增(激增的前提是多个线程已进入死锁或死循环。如果一个线程进入死锁或死循环,则CPU使用率应为100%左右)。本文主要介绍如何快速定位无限循环,死锁位置的原理相同。

案例演示

为了演示无限循环,本文使用以下代码作为演示示例:

package com.feng.home;
public class EndLessLoopDemo {
    public static void main(String[] args) {
        for(int i=0; i<10; i--){
            System.out.println("endless loop !");
        }
    }
}

打包代码并上传到服务器

在执行代码之前,首先查看服务器的资源使用情况,使用top命令,然后按1键,资源使用情况如下:

如何定位死循环或高cpu使用率(linux)_循环定位软件有什么_linux内核占用cpu高

如何定位死循环或高cpu使用率(linux)

image.png

从图中可以看出,服务器资源为24个核心,每个核心的使用不超过10%

接下来执行java命令以启动EndLessLoopDemo程序,该命令如下:

java -classpath home.jar com.feng.home.EndLessLoopDemo > /dev/null &

执行命令后,再次检查系统资源的使用情况:

如何定位死循环或高cpu使用率(linux)_linux内核占用cpu高_循环定位软件有什么

如何定位死循环或高cpu使用率(linux)

image.png

从上图可以看出,EndLessLoopDemo的进程号为15752,cpu使用率一直保持在10 0. 3%。当您查看每个核心时,您可以清楚地看到其中一个核心(图中cpu1 4)的利用率为6 6. 9%,利用率非常高。如果我们仅实现一个非常简单的逻辑要求,并且不消耗cpu资源,我们应该意识到,您自己的程序必定有问题。

故障排除

为了排除故障,我们应该打印出进程的线程堆栈信息,检查繁忙的线程在做什么,并使用jstack命令

jstack 15752 > stack.info

如何定位死循环或高cpu使用率(linux)_linux内核占用cpu高_循环定位软件有什么

获取线程堆栈信息后,您可以查看文件。由于线程很多,我们如何快速地在无限循环中找到线程?想象一下,如果程序有一个无限循环,首先,线程的运行状态应该是Runnable(除非在循环中使用了sleep,wait等操作);其次,程序应该执行自己编写的代码,只需搜索您自己的程序包名称就足够了。如果您搜索自己的程序包名称,则可以检查线程运行到的语句,找到代码中的位置,并检查是否存在无限循环。

在这种情况下,我们需要找到com.feng.home并执行命令:

grep -B20 'com.feng.home' stack.info | more

输出结果如下:

"main" #1 prio=5 os_prio=0 tid=0x00007ff664008800 nid=0x3d89 runnable [0x00007ff66ddc0000]
   java.lang.Thread.State: RUNNABLE
        at java.io.FileOutputStream.writeBytes(Native Method)
        at java.io.FileOutputStream.write(FileOutputStream.java:326)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
        - locked <0x00000003d3209700> (a java.io.BufferedOutputStream)
        at java.io.PrintStream.write(PrintStream.java:482)
        - locked <0x00000003d3208b50> (a java.io.PrintStream)
        at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
        at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
        at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
        - locked <0x00000003d3208b38> (a java.io.OutputStreamWriter)
        at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
        at java.io.PrintStream.write(PrintStream.java:527)
        - eliminated <0x00000003d3208b50> (a java.io.PrintStream)
        at java.io.PrintStream.print(PrintStream.java:669)
        at java.io.PrintStream.println(PrintStream.java:806)
        - locked <0x00000003d3208b50> (a java.io.PrintStream)
        at com.feng.home.EndLessLoopDemo.main(EndLessLoopDemo.java:8)

从输出结果中,我们可以看到主线程正在执行EndLessLoopDemo类中的第8行代码,而第8行代码是

循环定位软件有什么_如何定位死循环或高cpu使用率(linux)_linux内核占用cpu高

System.out.println("endless loop !");

因为我们可以检查循环条件是否存在问题,即找到无限循环的位置。

摘要

线程的无限循环不会填满一个cpu核心,因为它是一个时间片循环,它将导致某些cpu核心的利用率大大提高,但是该进程的cpu利用率必须为100%+(不包括线程睡眠和等待的情况。)

如果在无限循环语句块中执行n个线程,则CPU使用率通常约为n * 100%。因此,如果在简单的逻辑要求中有一个飞涨的杯子,则应首先找出程序中是否存在死循环或死锁(检测死锁也位于jstack输出中,只需找到死锁即可)

无限循环的常见情况摘要

    public void endLessLoop(boolean isDone){
        int retry = 0;
        while(retry < 3){
            if(isDone){
                continue;
            }
            retry++;
        }
    }

    public void endLessLoop(){
        int retry = 0;
        while(retry < 3){
            try{
                Integer.parseInt("aaa");
                retry++;
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

因此,必须仔细使用while循环。如果循环是for循环,则没有问题。使用while循环时,必须使用主要详细信息。


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shoujiruanjian/article-319118-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...