我在Java中有一个方法可以调用其他几种方法。从固定线程池中的多个线程调用此方法。工作线程数与可用处理器(核心数)相同。
public void query() {
method1();
method2();
}
当我使用VisualVM分析程序执行时,method1()
和method2()
次的时间非常短,但query()
自我时间非常长。但除了两个调用之外,该方法没有其他代码。 method1()
和method2()
内部可能存在同步,但在我控制的代码中没有明显的同步。
当我将池中的工作人员数量减少到1时,这个自我时间几乎消失了。整个程序的单线程和多线程执行时间几乎相同。我认为这意味着我的方法query()
正在等待某事。
没有死锁,执行完好无损。两个方法method1()
和method2()
调用了许多其他东西,包括混淆jar中的库类,所以我调试它并不容易。但是,使用query()
直接从工作线程调用java.util.concurrent.ExecutorService
方法。
答案 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)。虽然您可能无法在那里解决问题,但您可以一直介入混淆代码。但是你会知道延迟的位置。