代码准备 死循环
import java.util.ArrayList;
import java.util.List;
/**
* @author Kiand
* @date 2022/9/18 19:04
*/
public class dieForTest {
public static void main(String[] args) {
String data = "{\"data\":[{\"partnerid\"},{\"partnerid\"},{\"partnerid\"}]}";
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;
}
}
部署
普通类打 jar 包步骤
后面把 jar 包丢到 linux 中并启动
1.访问死循环方法对应的 url 地址执行死循环代码,top 查看运行的 jar 的进程 ID
可以发现44587这个线程使用cpu达到了98.7
2.使用命令 实验 jstack 获取对应进程的线程堆栈信息,下载到本地查看
jstack 44587 >44587.txt
3.top -p 45587 -H 查看进程中cpu利用率最高的线程ID记录下来在jstack导出的文件中查看对应信息
4.使用printf “%x” 44588 转化为16进制然后在jstack导出的文件中查找对应线程ID的信息
5.通过在jstack导出的文件中查看这个线程的方法栈信息可以确定到运行的方法,定位到问题所在,分析代码是否出现了死循环或者是其他原因。
代码准备 死锁
import java.util.concurrent.locks.ReentrantLock;
/**
* @author Kiand
* @date 2022/9/19 2:03
*/
public class DieLockTest {
static ReentrantLock lock1 = new ReentrantLock();
static ReentrantLock lock2 = new ReentrantLock();
public static void main(String[] args) {
deadlock();
}
/**
* 死锁
* */
public static String deadlock(){
new Thread(()->{
synchronized(lock1) {
try {Thread.sleep(1000);}catch(Exception e) {}
synchronized(lock2) {
System.out.println("Thread1 over");
}
}
}) .start();
new Thread(()->{
synchronized(lock2) {
try {Thread.sleep(1000);}catch(Exception e) {}
synchronized(lock1) {
System.out.println("Thread2 over");
}
}
}) .start();
return "deadlock";
}
}
1.访问该路径执行这段代码
2.jps查看对应java进程信息
3.jstack 并导出查看
4.根据jstack导出的文件,查看发生死锁的两个线程的详细信息记录。可以很清楚的定位死锁的位置
总结
当发现服务器CPU负载利用率很高时,分析可能出现了死循环或者死锁,通过工具来分析定位问题所在。
死循环:
1、用top查看cpu利用率最高的进程,并用jstack将其进程信息文件导出,
2、用top -p pid -H 查看进程中cpu占用率高的线程,在jstack文件中查询该线程的方法栈信息以定位到问题代码。
死锁:
1、jstack导出进程信息后,查看出现死锁的线程,
2、定位线程中出现死锁的方法,重新设计该段代码排除掉死锁。
补充:导致CPU负载变高的还有其他的原因如频繁的磁盘IO导致进程阻塞,导致CPU利用率飙高的原因也有可能是频繁的GC,具体问题具体解决,都可以使用工具来定位到问题所在。