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

来源:互联网 发布:怎么样编程 编辑:程序博客网 时间:2024/06/16 22:42

(源自: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如何帮我们检测到死锁。我们对此程序进行调试,发现程序好像被卡在那里,没有任何输出:

 

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

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

我们还可以追溯到发生死锁的代码的调用栈,可以很快地找到死锁发生的地方。

原创粉丝点击