您的位置:首页 > 编程语言 > Java开发

Netbeans 6.5 在多线程环境下的调试

2010-09-15 16:49 288 查看
(源自:http://developers.sun.com.cn/blog/functionalca/entry/netbeans_6_5_%E5%9C%A8%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84%E8%B0%83%E8%AF%95

Netbeans 6.5 在多线程环境下的调试

作者:Yuanxin Li

Netbeans 6.5里面的代码调试功能相对于以前的版本有了较大的改变,在Netbeans 6.5里面,我们现在可以对多线程的程序进行单步调试,可以检测死锁,另外,还加入了Javascript的调试工具,可以在IE,FireFox中调试客户端的javascript代码。本文主要关注于Netbeans 6.5里面的多线程环境下的调试,下一篇文章将介绍对Javascript的调试。

1、多线程的单步调试:

假设有如下一个类ThreadDebugging.java:

public class ThreadDebugging {

public static void main(String args[]) {
MyThread thread1 = new MyThread("Thread One");
MyThread thread2 = new MyThread("Thread Two");

Executor exec = Executors.newFixedThreadPool(4);
exec.execute(thread1);
exec.execute(thread2);

}

public static class MyThread implements Runnable {

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public MyThread(String threadName) {
this.setName(threadName);
}

public void run() {
for (int ii = 0; ii < 50; ii++) {
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
System.err.println("InterruptedException=" + ex.getMessage());
}
System.out.println("Thread " + this.getName() + " running...");
double random=Math.random();
System.out.println("Thread " + this.getName() +" Random #=" + random);
}

}
}
}

程序非常简单,只是创建了两个自定义的线程,线程执行的时候(run)在一个循环里先sleep 2000ms,然后再打印一些东西出来。在以往的Netbeans版本中,我们如果在

for (int ii = 0; ii < 50; ii++)

这行加上断点进行调试的时候,并不能有效地监测每一个线程执行的情况(变量的变化等),而在Netbeans 6.5里面,我们设置断点,并进行调试的时候,就可以只对某一个线程进行观测:



在上图中,程序在第43行遇到断点,相应的,在下面的那个窗口里面,“pool-1-thread-2”被标为绿色,意思为第一个线程池(定义见Executor exec = Executors.newFixedThreadPool(4);)的第二个线程被激活,按F8键进入下一步,直至第49行:



我们从上图的下面那个窗口可以看到,pool-1-thread-2已经执行到地49行,而pool-1-thread-1还是停留在第43行。这时,我们在pool-1-thread-1那行点击右键,选择“激活”:



这时,程序被切换到线程1的执行状态下(pool-1-thread-1被标为绿色,并且程序断点重新跳到第43行):



按F8继续执行:



这时,我们在“局部变量”这个窗口中可以看到,name的值是"Thread One",这时,我们又将程序切换到线程2下(点击"pool-1-thread-2"的右键,选择激活):



在局部变量的窗口中可以看到,name的值是"Thread Two"。由此,我们可以看出,Netbeans 6.5可以在多线程的环境下对每个线程的执行情况进行单独的监测,这对于调试多线程程序作用是非常大的。

2、死锁检测:

假设有以下一段程序:

public class Main {

/**
* From Java Tutorial - http://java.sun.com/docs/books/tutorial/essential/concurrency/deadlock.html
*
* Alphonse and Gaston are friends, and great believers in courtesy.
* A strict rule of courtesy is that when you bow to a friend, you must
* remain bowed until your friend has a chance to return the bow.
* Unfortunately, this rule does not account for the possibility that two
* friends might bow to each other at the same time. This example
* application, Deadlock, models this possibility:
*
*/

static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public synchronized void bow(Friend bower) {
System.out.format("%s: %s has bowed to me!%n",
this.name, bower.getName());
bower.bowBack(this);
}
public synchronized void bowBack(Friend bower) {
System.out.format("%s: %s has bowed back to me!%n",
this.name, bower.getName());
}
}

public static void main(String[] args) {
final Friend alphonse = new Friend("Alphonse");
final Friend gaston = new Friend("Gaston");
new Thread(new Runnable() {
public void run() { alphonse.bow(gaston); }
}).start();
new Thread(new Runnable() {
public void run() { gaston.bow(alphonse); }
}).start();
}

}

明显地,Alphonse和Gaston这两个线程同时执行了bow方法,而bow方法里面又要执行bowBack方法(将自己传为参数),造成了死锁(更形象的解析见开头那段英文注释)。我们主要看一下Netbeans 6.5如何帮我们检测到死锁。我们对此程序进行调试,发现程序好像被卡在那里,没有任何输出:



点击菜单栏的调试-检测死锁:



在调试窗口中我们就可以看到死锁的情况了:



我们还可以追溯到发生死锁的代码的调用栈,可以很快地找到死锁发生的地方。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: