PRivate void searchButton_actionPerformed() { outputTA.setText("Searching for: " + searchTF.getText()); //Broken!! Too mUCh work in the Swing thread String[] results = lookup(searchTF.getText()); outputTA.setText(""); for (int i = 0; i < results.length; i++) { String result = results[i]; outputTA.setText(outputTA.getText() + '/n' + result); } } 假如你运行这段代码(完整的代码可以在这儿下载),你会立即发现存在一些问题。图2显示了查找运行中的一个屏幕截图。
private void searchButton_actionPerformed() { outputTA.setText("Searching for: " + searchTF.getText()); //the String[][] is used to allow access to // setting the results from an inner class final String[][] results = new String[1][1]; new Thread() { public void run() { results[0] = lookup(searchTF.getText()); } }.start(); outputTA.setText(""); for (int i = 0; i < results[0].length; i++) { String result = results[0][i]; outputTA.setText(outputTA.getText() + '/n' + result); } } 这种方法有很多问题。注重final String[][] 。这是一个处理匿名内部类和作用域的不得已的替代。基本上,在匿名内部类中使用的,但在外部环绕类作用域中定义的任何变量都需要定义为final。你可以通过创建一个数组来持有变量解决这个问题。这样的话,你可以创建数组为final的,修改数组中的元素,而不是数组的引用自身。既然我们已经解决这个问题,让我们进入真正的问题所在吧。图3显示了这段代码运行时发生的情况:
private void searchButton_actionPerformed() { outputTA.setText("Searching for: " + searchTF.getText()); final String[][] results = new String[1][1]; new Thread() { public void run() { //get results. results[0] = lookup(searchTF.getText()) // send runnable to the Swing thread // the runnable is queued after the // results are returned SwingUtilities.invokeLater( new Runnable() { public void run() { // Now we're in the Swing thread outputTA.setText(""); for (int i = 0; i < results[0].length; i++) { String result = results[0][i]; outputTA.setText( outputTA.getText() + '/n' + result); } } } ); } }.start();} 这可以工作,但是这样做令人非常头痛。我们不得不对通过匿名线程执行的顺序,我们还不得不处理困难的scooping问题。问题并不少见,并且,这只是一个非常简单的例子,我们已经碰到了作用域,变量传递,和执行顺序等一系列问题。相像一个更复杂的问题,包含了几层嵌套,共享的引用和指定的执行顺序。这种方法很快就失控了。