我如何检测我的方法等待的是什么?

时间:2015-04-20 12:01:01

标签: java multithreading profiler

我在Java中有一个方法可以调用其他几种方法。从固定线程池中的多个线程调用此方法。工作线程数与可用处理器(核心数)相同。

public void query() {
    method1();
    method2();
}

当我使用VisualVM分析程序执行时,method1()method2()次的时间非常短,但query()自我时间非常长。但除了两个调用之外,该方法没有其他代码。 method1()method2()内部可能存在同步,但在我控制的代码中没有明显的同步。

当我将池中的工作人员数量减少到1时,这个自我时间几乎消失了。整个程序的单线程和多线程执行时间几乎相同。我认为这意味着我的方法query()正在等待某事。

没有死锁,执行完好无损。两个方法method1()method2()调用了许多其他东西,包括混淆jar中的库类,所以我调试它并不容易。但是,使用query()直接从工作线程调用java.util.concurrent.ExecutorService方法。

4 个答案:

答案 0 :(得分:5)

针对正在运行的进程在级别3发出kill命令。所有线程都会将堆栈跟踪转储到标准输出,应用程序将继续运行。

kill -3 <pid>

注意,您在控制台上看不到发出kill命令的任何内容。 Java应用程序本身将具有输出。您可能需要检查日志,具体取决于应用程序重定向其输出的位置。

答案 1 :(得分:1)

我在自定义锁定机制中包装另一个类的代理类中发现了问题。

我继续创建一系列Thread Dumps。由于我使用JVisualVM进行性能分析,因此我在此过程中创建了一些Thread Dump。 Ctrl+Break也有效,与Synesso在回答中提到的kill -3 <pid>相同。

我使用评论中提到的Thread Dump Analyzer来分析它们。我不知道该先找什么,但是由于TDA中的对象和监视器的链接,我发现了这样的东西:

"pool-9-thread-32" #304 prio=5 os_prio=0 tid=0x000000002a706800 nid=0x348c waiting for monitor entry [0x000000003f06e000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at com.example.MyClass.method1(MyClass.java:400)
    - waiting to lock <0x0000000680837b90> (a com.example.DifferentClass)
    at com.example.MyClass.query(MyClass.java:500)
    ... omitted ...
    at java.util.concurrent.FutureTask.run(FutureTask.java:270)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:618)
    at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
    - <0x000000075bc59aa8> (a java.util.concurrent.ThreadPoolExecutor$Worker)

DifferentClass扩展了抽象MyClass,并且有一个从method1()DifferentClass的调用,其中DTO对象被传递给执行大量处理的方法,记录最后保存到数据库。在创建其中一个数据库处理类时使用了代理类。

答案 2 :(得分:0)

您最好的选择是找到一种方法来获取正在运行的程序的堆栈跟踪。 Here是一种可能的方式。

答案 3 :(得分:0)

我建议在IDE中使用调试模式运行程序,并在可能出现问题的旁边放置断点。然后在程序延迟的时候进入(例如Netbeans中的F7)。虽然您可能无法在那里解决问题,但您可以一直介入混淆代码。但是你会知道延迟的位置。