如何在 IntelliJ 中调试多线程应用程序?
Posted
技术标签:
【中文标题】如何在 IntelliJ 中调试多线程应用程序?【英文标题】:How to debug a multi-threaded app in IntelliJ? 【发布时间】:2015-01-05 17:07:27 【问题描述】:我在 IntelliJ IDEA 14.0.2 中遇到了多个线程和断点的奇怪问题。断点之后的代码在停止之前执行。
import java.util.concurrent.atomic.AtomicInteger;
public class Main
private static final int NUM_CLIENTS = 1000;
static class TestRunnable implements Runnable
AtomicInteger lock;
@Override
public void run()
synchronized (this.lock)
int curCounter = this.lock.addAndGet(1);
System.out.println("Thread: " + Thread.currentThread().getName() + "; Count: " + curCounter);
if (curCounter >= NUM_CLIENTS)
lock.notifyAll();
public static void main(final String args[])
final AtomicInteger lock = new AtomicInteger(0);
for (int i = 0; i < NUM_CLIENTS; i++)
TestRunnable tr1 = new TestRunnable();
tr1.lock = lock;
new Thread(tr1).start();
synchronized (lock)
try
lock.wait();
catch (InterruptedException e)
e.printStackTrace();
System.out.println("Main woken up");
当我在第 12 行设置断点(全部暂停)时,synchronized (this.lock)
、System.out.println
仍会执行(有时会执行多次)。截图如下:
据我所知,所有线程都应该在断点处停止。
【问题讨论】:
如果将断点放在第 14 行会怎样? (println) 我可以向你保证,一个线程已经停止...哪个线程未确定。 这只是因为建立套接字连接需要一些时间。并且调试器需要建立连接才能在 JVM 中安装断点。对于这个时间很关键的情况(就像你的情况一样),有一个 JVM 选项可以暂停 JVM,直到建立连接。你的 IDE 应该有一个激活它的选项。 @David Schwartz:这将是一个奇怪的限制。例如。 Eclipse 没有这样的问题。而且从来没有。 @David Schwartz:显示当前堆栈跟踪的视图仅显示多个堆栈跟踪。实际上,该视图始终向您显示具有层次结构的树:“已启动的 JVM”→“正在运行的线程”→“堆栈跟踪”,因为您始终可以单击线程或 JVM 手动挂起线程或整个 JVM … 【参考方案1】:文档读起来令人困惑,但this is the relevant block. 归根结底是将属性设置为在线程上挂起,而不是在整个应用程序上挂起。这将导致您在每个单独的线程而不是任意的、不确定的线程上打断点。
暂停策略:全部 遇到断点时,所有线程都会暂停。 暂停策略:线程 当断点被命中时,断点所在的线程被挂起。【讨论】:
事实上,我想在任何线程遇到断点时暂停所有线程。就像 Eclipse 一样。我想这是不可能的? 事实上文档说:“全部 - 当一个断点被命中时,所有线程都被挂起”。这正是我想要的行为。问题是一些线程,有时,在断点被击中后继续执行,可能是当 IDEA 停止第一个线程击中断点时。我认为这只是 IDEA 调试器或 JVM 上的一个错误。他们至少应该澄清文档中的行为,因为它完全是错误的,而不是令人困惑的。 无论如何你的解决方案现在对我有用,非常感谢。 文档(针对 2017.2)还描述:“在某些情况下,IntelliJ IDEA 不会在断点处停止。考虑以下情况:在类的不同方法处设置两个断点,并且它们的暂停策略设置为全部。当其中一个断点被命中时,会执行一些单步操作。如果在单步执行另一个线程时遇到第二个断点,IntelliJ IDEA 将不会停在那里。" 升级到 2018.2 后我仍然看到该行为。以上是关于如何在 IntelliJ 中调试多线程应用程序?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 EclipseMe 中调试多线程 midlet 应用程序?
如何使用 IntelliJ 调试在 Docker 中运行的应用程序?