`
ryhome
  • 浏览: 44468 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

使用JProfiler跟踪阻塞线程的来源

阅读更多

在开发调测过程遇到线程非正常阻塞的情况是在所难免的, 有时是死锁, 有时是不正确的程序逻辑. 例如: 

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
0
0
分享到:
评论

相关推荐

    Jprofiler9.2使用手册.pdf

    JProfiler 是一个非常优秀的的 JVM 性能分析工具,可监视本地和远程的 JVM,适用于各种操作系统。 常用的功能有: 1、 监视堆内存占用情况和创建对象实例的数量,找出...3、 监视线程的阻塞与死锁 4、 监视 GC 的耗时。

    JProfiler检查内存泄漏

    JProfiler是一款Java的性能监控工具。可以查看当前应用的对象、对象引用、内存、CPU使用情况、线程、线程运行情况(阻塞、等待等),同时可以查找应用内存使用得热点。

    JProfiler入门教程

    3、监视线程的阻塞与死锁 4、监视GC的耗时。 监视本地JVM(Windows): 需要安装JProfiler windows版本 监视远程的JVM(Linux): 客户端需要安装JProfiler windows版本 服务需要安装JProfiler Linux版本 客户端与...

    jprofiler6,带SN

    可以查看当前应用的对象、对象引用、内存、CPU使用情况、线程、线程运行情况(阻塞、等待等),同时可以查找应用内存使用得热点,即:哪个对象占用的内存比较多;或者CPU热点,即:哪儿方法占用的较大得CPU资源。我...

    jprofiler 8.x 注册码

    可以查看当前应用的对象、对象引用、内存、CPU使用情况、线程、线程运行情况(阻塞、等待等),同时可以查找应用内存使用得热点,即:哪个对象占用的内存比较多;或者CPU热点,即:哪儿方法占用的较大得CPU资源。

    jprofiler9.2入门教程-安装配置和使用

    JProfiler 是一个非常优秀的的 JVM 性能分析工具,可监视本地和远程的 JVM,适用于各种操作系统。 常用的功能有: 1、 监视堆内存占用... 2、 监视占用 CPU 较多的方法 3、 监视线程的阻塞与死锁 4、 监视 GC 的耗时。

    jprofiler_windows_6_0_4.zip

    JProfiler是一款Java的性能监控工具。可以查看当前应用的对象、对象引用、内存、CPU使用情况、线程、线程运行情况(阻塞、等待等)

    JProfiler入门教程-1.1

    JProfiler 是一个非常优秀的的 JVM 性能分析工具,可监视本地和远程的 JVM,适用于各种操作系统。 常用的功能有: 1、 监视堆内存占用... 2、 监视占用 CPU 较多的方法 3、 监视线程的阻塞与死锁 4、 监视 GC 的耗时。

    jvm调优实用工具.rar

    jprofiler内存调优是一个很实用的工具,可以看到线程,类等使用的资源情况,还有是否阻塞等

    Mac版jvm性能调优工具+内存监控+系统性能分析+Java开发助手+三高性能分析必备+Jprofiler_12.0.4

    软件主要功能如下: (1)监控堆内存的占用情况和创建对象实例的数量,找出内存泄露的原因; (2)监控占用CPU较多的方法; (3)监控线程的阻塞和死亡; (4)监控GC的耗时;

Global site tag (gtag.js) - Google Analytics