通过编程发现Java死锁

简介: 通过stack也可以发现死锁。测试类import java.util.concurrent.TimeUnit;public class Test { public static void main(String[] args) { DeadlockDetector ...

通过stack也可以发现死锁。

测试类

import java.util.concurrent.TimeUnit;

public class Test {
    public static void main(String[] args) {
        DeadlockDetector deadlockDetector = new DeadlockDetector(new DeadlockConsoleHandler(), 5, TimeUnit.SECONDS);
        deadlockDetector.start();

        final Object lock1 = new Object();
        final Object lock2 = new Object();
        Thread thread1 = new Thread(()->{
            synchronized (lock1) {
                System.out.println("Thread1 acquired lock1");
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException ignore) {
                }
                synchronized (lock2) {
                    System.out.println("Thread1 acquired lock2");
                }
            }
        });
        thread1.start();
        Thread thread2 = new Thread(()->{
            synchronized (lock2) {
                System.out.println("Thread2 acquired lock2");
                synchronized (lock1) {
                    System.out.println("Thread2 acquired lock1");
                }
            }
        });
        thread2.start();
    }
}

处理类

public class DeadlockConsoleHandler implements DeadlockHandler {
    @Override
    public void handleDeadlock(final ThreadInfo[] deadlockedThreads) {
        if (deadlockedThreads != null) {
            System.err.println("Deadlock detected!");
            Map<Thread, StackTraceElement[]> stackTraceMap = Thread.getAllStackTraces();
            for (ThreadInfo threadInfo : deadlockedThreads) {
                if (threadInfo != null) {
                    for (Thread thread : Thread.getAllStackTraces().keySet()) {
                        if (thread.getId() == threadInfo.getThreadId()) {
                            System.err.println(threadInfo.toString().trim());
                            for (StackTraceElement ste : thread.getStackTrace()) {
                                System.err.println("t" + ste.toString().trim());
                            }
                        }
                    }
                }
            }
        }
    }
}
import java.lang.management.ThreadInfo;
public interface DeadlockHandler {
    void handleDeadlock(final ThreadInfo[] deadlockedThreads);
}

关键类

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class DeadlockDetector {

    private final DeadlockHandler deadlockHandler;
    private final long period;
    private final TimeUnit unit;
    private final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    final Runnable deadlockCheck = new Runnable() {
        @Override
        public void run() {
            long[] deadlockedThreadIds = mbean.findDeadlockedThreads();
            if (deadlockedThreadIds != null) {
                ThreadInfo[] threadInfos = mbean.getThreadInfo(deadlockedThreadIds);
                deadlockHandler.handleDeadlock(threadInfos);
            }
        }
    };

    public DeadlockDetector(final DeadlockHandler deadlockHandler, final long period, final TimeUnit unit) {
        this.deadlockHandler = deadlockHandler;
        this.period = period;
        this.unit = unit;
    }

    public void start() {
        this.scheduler.scheduleAtFixedRate(this.deadlockCheck, this.period, this.period, this.unit);
    }
}

测试结果

Thread1 acquired lock1
Thread2 acquired lock2
Deadlock detected!
"Thread-1" Id=12 BLOCKED on java.lang.Object@6a80bb83 owned by "Thread-0" Id=11
ttest.Test.lambda$main$1(Test.java:32)
ttest.Test$$Lambda$2/363771819.run(Unknown Source)
tjava.lang.Thread.run(Thread.java:745)
"Thread-0" Id=11 BLOCKED on java.lang.Object@6ebf220b owned by "Thread-1" Id=12
ttest.Test.lambda$main$0(Test.java:23)
ttest.Test$$Lambda$1/668386784.run(Unknown Source)
tjava.lang.Thread.run(Thread.java:745)
Deadlock detected!

 

相关实践学习
如何快速体验知识检索增强应用
在应用广场中您可以挑选智能体API应用、官方预置完整工程链路的知识检索增强(RAG)应用、流程编排应用,以及官方最佳实践的写作应用妙笔等,通过应用快速将通义千问系列等大语言模型能力接入到业务解决方案中。
目录
相关文章
|
14天前
|
Java 程序员
Java编程中的异常处理:从基础到高级
在Java的世界中,异常处理是代码健壮性的守护神。本文将带你从异常的基本概念出发,逐步深入到高级用法,探索如何优雅地处理程序中的错误和异常情况。通过实际案例,我们将一起学习如何编写更可靠、更易于维护的Java代码。准备好了吗?让我们一起踏上这段旅程,解锁Java异常处理的秘密!
|
17天前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
|
17天前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
11天前
|
安全 算法 Java
Java多线程编程中的陷阱与最佳实践####
本文探讨了Java多线程编程中常见的陷阱,并介绍了如何通过最佳实践来避免这些问题。我们将从基础概念入手,逐步深入到具体的代码示例,帮助开发者更好地理解和应用多线程技术。无论是初学者还是有经验的开发者,都能从中获得有价值的见解和建议。 ####
|
11天前
|
Java 调度
Java中的多线程编程与并发控制
本文深入探讨了Java编程语言中多线程编程的基础知识和并发控制机制。文章首先介绍了多线程的基本概念,包括线程的定义、生命周期以及在Java中创建和管理线程的方法。接着,详细讲解了Java提供的同步机制,如synchronized关键字、wait()和notify()方法等,以及如何通过这些机制实现线程间的协调与通信。最后,本文还讨论了一些常见的并发问题,例如死锁、竞态条件等,并提供了相应的解决策略。
30 3
|
16天前
|
开发框架 安全 Java
Java 反射机制:动态编程的强大利器
Java反射机制允许程序在运行时检查类、接口、字段和方法的信息,并能操作对象。它提供了一种动态编程的方式,使得代码更加灵活,能够适应未知的或变化的需求,是开发框架和库的重要工具。
34 2
|
17天前
|
安全 Java 开发者
Java中的多线程编程:从基础到实践
本文深入探讨了Java多线程编程的核心概念和实践技巧,旨在帮助读者理解多线程的工作原理,掌握线程的创建、管理和同步机制。通过具体示例和最佳实践,本文展示了如何在Java应用中有效地利用多线程技术,提高程序性能和响应速度。
52 1
|
Java
java并发编程:死锁代码示例
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
141 0
|
Java
一个简单的Java死锁示例(转)
在实际编程中,要尽量避免出现死锁的情况,但是让你故意写一个死锁的程序时似乎也不太简单(有公司会出这样的面试题),以下是一个简单的死锁例子,程序说明都写着类的注释里了,有点罗嗦,但是应该也还是表述清楚了的。
812 0