Varias herramientas para detectar puntos muertos: JStack, JConsole, JVisualVM, ThreadMXBean

El interbloqueo es un problema que debe evitarse en el desarrollo, ya que provocará que los subprocesos no se ejecuten y problemas de funcionamiento. Aquí hay cuatro formas de localizar un punto muerto.

1. Ejemplo de interbloqueo

Primero, veamos un ejemplo simple de interbloqueo

public class SynchronizedTest {

	public static void main(String[] args) throws InterruptedException {
		DealThread t1 = new DealThread();
		t1.setFlag("a");
		Thread thread1 = new Thread(t1);
		thread1.start();
		
		Thread.sleep(1000);
		
		t1.setFlag("b");
		Thread thread2 = new Thread(t1);
		thread2.start();
	}
	
	static class DealThread implements Runnable{
		public String username;
		public Object lock1 = new Object();
		public Object lock2 = new Object();
		public void setFlag(String username) {
			this.username = username;
		}
		
		@Override
		public void run() {
			if("a".equals(username)) {
				synchronized (lock1) {
					try {
						System.out.println("username= " + username);
						Thread.sleep(3000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					synchronized(lock2) {
						System.out.println("按lock1->lock2代码顺序执行了");
					}
				}
			}
			if("b".equals(username)) {
				synchronized (lock2) {
					try {
						System.out.println("username= " + username);
						Thread.sleep(3000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					synchronized(lock1) {
						System.out.println("按lock2->lock1代码顺序执行了");
					}
				}
			}
		}
	}
}

2.JStack

JStack es una herramienta de línea de comandos que viene con JDK, que se utiliza principalmente para el análisis de volcado de subprocesos. El archivo de volcado es una imagen de memoria del subproceso y guarda la información del estado de ejecución del proceso. Su ubicación está en el directorio JAVA_HOME / bin. No es una interfaz gráfica, por lo que no se puede abrir haciendo doble clic.
Primero abra la línea de comando CMD, ejecute el comando jps, vea la información del proceso de Java, averigüe el número del proceso de Java a depurar, que es pid, aquí es 12980,
Inserte la descripción de la imagen aquí
ejecute jstack -l pid, -l los parámetros pueden imprimir la información relacionada con el bloqueo, si Es un proyecto real que puede imprimir mucha información, podemos usar el comando jstack -l pid> D: deal_thread.log para imprimir toda la información en el archivo deal_thread.log.
Hay muchos resultados de impresión, solo se intercepta información sobre interbloqueos

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x000000000363d9d8 (object 0x00000000d5cf9808, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x000000000363d878 (object 0x00000000d5cf9818, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at com.morlia.platform.synchronizedtest.SynchronizedTest$DealThread.run(SynchronizedTest.java:69)
        - waiting to lock <0x00000000d5cf9808> (a java.lang.Object)
        - locked <0x00000000d5cf9818> (a java.lang.Object)
        at java.lang.Thread.run(Unknown Source)
"Thread-0":
        at com.morlia.platform.synchronizedtest.SynchronizedTest$DealThread.run(SynchronizedTest.java:55)
        - waiting to lock <0x00000000d5cf9818> (a java.lang.Object)
        - locked <0x00000000d5cf9808> (a java.lang.Object)
        at java.lang.Thread.run(Unknown Source)

Found 1 deadlock.

En este momento, se puede ver en la información impresa que los subprocesos Thread-0 y Thread-1 están bloqueados en el método de ejecución.

3.JConsole

JConsole es una herramienta de monitoreo de máquinas virtuales que viene con el JDK. Su ubicación está en el directorio JAVA_HOME / bin. Después de hacer doble clic para abrirlo, seleccione el hilo que puede interbloquearse y haga clic en Conectar.
Inserte la descripción de la imagen aquí
Después de ingresar a la página de monitoreo, primero haga clic en el hilo y luego haga clic en el punto muerto de detección en la esquina inferior izquierda.
Inserte la descripción de la imagen aquí
Si ocurre un punto muerto, la información del hilo del punto muerto aparecerá en la columna del punto muerto.
Inserte la descripción de la imagen aquí
Esta información es similar a la información impresa por jstack

4.JVisualVM

JVisualVM es una herramienta muy poderosa para solucionar problemas de programas Java proporcionada por jdk, que puede monitorear el rendimiento del programa, ver información de configuración de jvm, instantáneas de pila e información de pila de subprocesos. Es una herramienta esencial para la optimización de programas. La herramienta se encuentra en el directorio bin del JDK y también es una interfaz gráfica, que se puede abrir directamente haciendo doble clic.
Inserte la descripción de la imagen aquí
Seleccione el proceso que necesita ver a la izquierda, haga clic en la pestaña del proceso a la derecha y luego haga clic en la pestaña del hilo. En este momento, podemos ver una letra roja que indica que se ha detectado un interbloqueo, por lo que hacemos clic en Thread Dump para obtener más información.
En este momento, aparecerá la página threaddump, la información anterior es la información del archivo de volcado.
Inserte la descripción de la imagen aquí

5.ThreadMXBean

A veces, queremos que el programa encuentre el punto muerto por sí solo, en lugar de necesitar que nosotros lo encontremos. Java proporciona estas clases de herramientas.
Código de muestra:

public class SynchronizedTest {

	public static void main(String[] args) throws InterruptedException {
		DealThread t1 = new DealThread();
		t1.setFlag("a");
		Thread thread1 = new Thread(t1);
		thread1.start();
		
		Thread.sleep(1000);
		
		t1.setFlag("b");
		Thread thread2 = new Thread(t1);
		thread2.start();
		
		Thread.sleep(4000);
		
		//获取xbean实例
		ThreadMXBean mBean = ManagementFactory.getThreadMXBean();
		//获取死锁的线程ID
		long[] dealThreads = mBean.findDeadlockedThreads();
		//遍历
		for(long pid : dealThreads) {
			//获取线程信息
			ThreadInfo threadInfo = mBean.getThreadInfo(pid);
			System.out.println(threadInfo);
		}
	}
	
	static class DealThread implements Runnable{
		public String username;
		public Object lock1 = new Object();
		public Object lock2 = new Object();
		public void setFlag(String username) {
			this.username = username;
		}
		
		@Override
		public void run() {
			if("a".equals(username)) {
				synchronized (lock1) {
					try {
						System.out.println("username= " + username);
						Thread.sleep(3000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					synchronized(lock2) {
						System.out.println("按lock1->lock2代码顺序执行了");
					}
				}
			}
			if("b".equals(username)) {
				synchronized (lock2) {
					try {
						System.out.println("username= " + username);
						Thread.sleep(3000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					synchronized(lock1) {
						System.out.println("按lock2->lock1代码顺序执行了");
					}
				}
			}
		}
	}
}

resultado de la operación

username= a
username= b
"Thread-1" Id=11 BLOCKED on java.lang.Object@15db9742 owned by "Thread-0" Id=10
"Thread-0" Id=10 BLOCKED on java.lang.Object@6d06d69c owned by "Thread-1" Id=11

La detección de puntos muertos y la obtención de información de la pila son operaciones que consumen más rendimiento y no se pueden utilizar con frecuencia.
El interbloqueo es un error en el diseño del programa. Al diseñar un programa, evite que ambas partes se mantengan bloqueadas. Mientras esperen a que el otro lo libere, puede producirse un interbloqueo.

Supongo que te gusta

Origin blog.csdn.net/d303577562/article/details/109225983
Recomendado
Clasificación