一、实战死循环导致CPU飙高
top -p pid -H
jstack pid
printf "%s" 十进制的线程id
二、创建CUP100%实例(死循环)
1、创建CpuController
@RestController public class CpuController { @RequestMapping("/loop") public List<Long> loop(){ String data = "{"data":[{"partnerid":]}"; return getPartneridsFromJson(data); } public static List<Long> getPartneridsFromJson(String data){ //{"data":[{"partnerid":982,"count":"10000","cityid":"11"},{"partnerid":983,"count":"10000","cityid":"11"},{"partnerid":984,"count":"10000","cityid":"11"}]} //上面是正常的数据 List<Long> list = new ArrayList<Long>(2); if(data == null || data.length() <= 0){ return list; } int datapos = data.indexOf("data"); if(datapos < 0){ return list; } int leftBracket = data.indexOf("[",datapos); int rightBracket= data.indexOf("]",datapos); if(leftBracket < 0 || rightBracket < 0){ return list; } String partners = data.substring(leftBracket+1,rightBracket); if(partners == null || partners.length() <= 0){ return list; } while(partners!=null && partners.length() > 0){ int idpos = partners.indexOf("partnerid"); if(idpos < 0){ break; } int colonpos = partners.indexOf(":",idpos); int commapos = partners.indexOf(",",idpos); if(colonpos < 0 || commapos < 0){ //partners = partners.substring(idpos+"partnerid".length());//1 continue; } String pid = partners.substring(colonpos+1,commapos); if(pid == null || pid.length() <= 0){ //partners = partners.substring(idpos+"partnerid".length());//2 continue; } try{ list.add(Long.parseLong(pid)); }catch(Exception e){ //do nothing } partners = partners.substring(commapos); } return list; } }
getPartneridsFromJson发生死循环
2.打包
D:workspacemonitor_tuning>mvn clean package -Dmaven.test.skip
pom.xml的配置如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>monitor_tuning</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>monitor_tuning</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<!-- compile for Java 1.8 -->
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<compilerArgs>
<!-- 过期的方法的警告-->
<arg>-Xlint:deprecation</arg>
</compilerArgs>
<compilerArguments>
<!-- 是否输出所有的编译信息(包括类的加载等)-->
<!--<verbose />-->
<!-- 解决maven命令编译报错,因为rt.jar 和jce.jar在jre的lib下面,不在jdk的lib下面,
导致maven找不到(java7以后会出现这个问题),将这2个jar包拷贝到jdk的lib下面估计也好使-->
<bootclasspath>${java.home}lib
t.jar;${java.home}libjce.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
端口设置为9080

3、生成jar完成后,将它放在测试服务器
nohup java -jar monitor_tuning-0.0.1-SNAPSHOT.jar
四、我这里是将 monitor_tuning以war包的的形式部署到我的测试服务器
1)打开多个页面调用loop方法
http://*.*.*.*:7080/monitor_tuning/loop
2)使用top命令查看cpu的使用

3、jstack 20738 > 20738.txt
sz 20738.txt 下载文件
4、 打印所有的线程
top -p 20738 -H

打印946为10进制,结果为3b2

打开刚才的20738.txt文件
查找3b2

这样就定位到了getPartneridsFromJson这个方法。
三、创建CUP100%实例(死锁)
创建两个线程,线程1先获得锁1,然后获得锁2; 线程二先获得锁2,然后获得锁1. 然后两个线程造成死锁。
private Object lock1 = new Object();
private Object lock2 = new Object();
/**
* 死锁
*/
@RequestMapping("/deadlock")
public String deadlock(){
new Thread(()->{
synchronized (lock1){
try {
Thread.sleep(1000);
synchronized (lock2){
System.out.println("Thread1 over");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(()->{
synchronized (lock2){
try {
Thread.sleep(1000);
synchronized (lock1){
System.out.println("Thread2 over");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
return "deadlock";
}
jstack 8704 > 8704.txt 8704为tomcat的进程
将8704.txt拉到底部,可以看到死锁的信息。
Found one Java-level deadlock: ============================= "Thread-9": waiting to lock monitor 0x0000000000eaeb08 (object 0x00000000f6d7abf8, a java.lang.Object), which is held by "Thread-8" "Thread-8": waiting to lock monitor 0x00007f82ac0062c8 (object 0x00000000f6d7ac08, a java.lang.Object), which is held by "Thread-9" Java stack information for the threads listed above: =================================================== "Thread-9": at com.example.monitor_tuning.chapter2.CpuController.lambda$deadlock$1(CpuController.java:52) - waiting to lock <0x00000000f6d7abf8> (a java.lang.Object) - locked <0x00000000f6d7ac08> (a java.lang.Object) at com.example.monitor_tuning.chapter2.CpuController$$Lambda$389/1326472202.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) "Thread-8": at com.example.monitor_tuning.chapter2.CpuController.lambda$deadlock$0(CpuController.java:39) - waiting to lock <0x00000000f6d7ac08> (a java.lang.Object) - locked <0x00000000f6d7abf8> (a java.lang.Object) at com.example.monitor_tuning.chapter2.CpuController$$Lambda$388/1104652864.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) Found 1 deadlock.