在开发调测过程遇到线程非正常阻塞的情况是在所难免的, 有时是死锁, 有时是不正确的程序逻辑. 例如:
package demo;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
private static final String DEATH_TAG = "exit";
private static BlockingQueue<String> taskList = new LinkedBlockingQueue<String>();
public static void main(String[] args)throws Exception {
ExecutorService es = Executors.newCachedThreadPool();
// 创建一个新线程,使用阻塞队列接收字符串, 如果不放入DEATH_TAG, 则一直进行处理
es.submit(new Runnable() {
@Override
public void run() {
while (true) {
String s = null;
try {
s = taskList.take();
if (DEATH_TAG.equals(s)) {
System.out.println("bye");
break;
}
System.out.println(s);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
// taskList.put(DEATH_TAG);
es.shutdown();
}
}
如果程序结束前没有放入DEATH_TAG, 整个程序都不能正常退出, 就在那里一直阻塞.
出现了线程阻塞, 通常我们会使用jdk自带的jstack或者jconsole命令, 或者eclipse的debug模式, 查看当前线程堆栈情况. 可以看到是线程"pool-1-thread-1"没有退出:
线程stack信息:
"pool-1-thread-1" prio=6 tid=0x0b94fc00 nid=0x1708 waiting on condition [0x0bf1f000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x03d2a980> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1925)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:358)
at demo.Main$1.run(Main.java:23)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
但是stack信息只有jdk自带类的方法调用过程, 我们并看不出到底是哪个对象创建了这个线程, 这阻碍了我们的调测.
这时, JProfiler的"Thread Views"功能则发挥了作用. 使用"Thread Views"可以清楚的看到每个线程的创建情况, 从而清楚的看到线程的创建者是"demo.Main":
- 大小: 16.2 KB
- 大小: 37.8 KB
分享到:
相关推荐
6. **线程分析**:探讨如何使用JProfiler监控线程状态,定位死锁和阻塞问题,提升并发性能。 7. **Garbage Collection监控**:讲解如何通过JProfiler观察垃圾回收过程,分析GC行为对系统性能的影响。 8. **JVM配置...
- **线程分析**:实时查看线程状态,识别死锁和阻塞,有助于调试多线程问题。 - **JVM配置优化**:提供对JVM参数的详细视图,帮助调整垃圾回收器、类加载器等配置,提升系统性能。 - **GUI和事件分析**:监测...
JProfiler 是一个非常优秀的的 JVM 性能分析工具,可监视本地和远程的 JVM,适用于各种操作系统。 常用的功能有: 1、 监视堆内存占用情况和创建对象实例的数量,找出...3、 监视线程的阻塞与死锁 4、 监视 GC 的耗时。
对于多线程应用,JProfiler11提供实时线程快照,显示线程状态和阻塞情况,有助于排查死锁和线程竞争问题。此外,它还支持线程挂起和恢复操作,便于进行调试。 **方法Profiling** JProfiler11支持方法级别的性能剖析...
3. 线程分析:查看线程状态,定位死锁和阻塞问题。 4. 监控JVM参数:实时查看和调整JVM的配置参数。 5. 数据库连接分析:检查数据库查询性能,发现慢查询。 6. 网络I/O和文件I/O监控:评估系统I/O性能。 通过这些...
JProfiler是一款强大的Java性能分析工具,它可以帮助开发者深入洞察应用程序的内存使用、CPU消耗、线程活动等关键性能指标。本文将详细介绍JProfiler的安装步骤以及基本使用方法。 ## 一、JProfiler的下载与安装 1...