您现在的位置: 天极网 > 开发频道 > 再论Java Swing线程
全文

再论Java Swing线程

2003-11-10 17:28作者:不详出处:论坛责任编辑:方舟
  线程

  到现在,我们已经解决了上面的异步问题;通过监听器使组件脱耦,通过事件对象传递变量,通过事件产生和监听器的注册的组合决定执行的顺序。让我们回到线程问题,因为正是它把我们带到了这儿。实际上非常容易:因为我们已经有了异步功能的监听器,我们可以简单地让监听器自己决定它们应该在哪个线程中执行。考虑UI类和LookupManager的分离。UI类基于事件,决定需要什么处理。并且,该类也是Swing,而日志类不是。所以让UI类负责决定它应该在什么线程中执行将更加有意义。所以,让我们再次看看UI类。下面是没有线程的lookupCompleted()方法:

public void lookupCompleted(final LookupEvent e) {
 outputTA.setText("");
 String[] results = e.getResults();
 for (int i = 0; i < results.length; i++) {
  String result = results[i];
  outputTA.setText(outputTA.getText() + "\n" + result);
 }
}

  我们知道这将在非Swing线程中调用,因为该事件是直接在LookupManager中触发的,这将不是在Swing线程中执行。因为所有的代码功能上都是异步的(我们不必等待监听器方法允许结束后才调用其它代码),我们可以通过SwingUtilities.invokeLater()将这些代码改道到Swing线程。下面是新的方法,传入一个匿名Runnable到SwingUtilities.invokeLater():

public void lookupCompleted(final LookupEvent e) {
 //notice the threading
 SwingUtilities.invokeLater( new Runnable() {
  public void run() {
   outputTA.setText("");
   String[] results = e.getResults();
   for (int i = 0; i < results.length; i++) {
    String result = results[i];
    outputTA.setText(outputTA.getText() + "\n" + result);
   }
  }
 }
);
}

  如果任何LookupListener不是在Swing线程中执行,我们可以在调用线程中执行监听器代码。作为一个原则,我们希望所有的监听器都迅速地接到通知。所以,如果你有一个监听器需要很多时间来处理自己的功能,你应该创建一个新的线程或者把耗时代码放入ThreadPool中等待执行。

  最后的步骤是让LookupManager在非Swing线程中执行lookup。当前,LookupManager是在JButton的ActionListener的Swing线程中被调用的。现在是我们做出决定的时候,或者我们在JButton的ActionListener中引入一个新的线程,或者我们可以保证lookup自己在非Swing线程中执行,自己开始一个新的线程。我选择尽可能和Swing类贴近地管理Swing线程。这有助于把所有Swing逻辑封装在一起。如果我们把Swing线程逻辑添加到LookupManager,我们将引入了一层不必要的依赖。并且,对于LookupManager在非Swing线程环境中孵化自己的线程是完全没有必要的,比如一个非绘图的用户界面,在我们的例子中,就是Logger。产生不必要的新线程将损害到你应用的性能,而不是提高性能。LookupManager执行的很好,不管Swing线程与否--所以,我喜欢把代码集中在那儿。

  现在我们需要将JButton的ActionListener执行lookup的代码放在一个非Swing线程中。我们创建一个匿名的Thread,使用一个匿名的Runnable执行这个lookup。

private void searchButton_actionPerformed() {
 new Thread(){
  public void run() {
   lookupManager.lookup(searchTF.getText());
  }
 }.start();
}

  这就完成了我们的Swing线程。简单地在actionPerformed()方法中添加线程,确保监听器在新的线程中执行照顾到了整个线程问题。注意,我们不用处理像第一个例子那样的任何问题。通过把时间花费在定义一个事件驱动的体系,我们在和Swing线程相关处理上节约了更多的时间。

  结论

  如果你需要在同一个方法中执行大量的Swing代码和非Swing代码,很容易将某些代码放错位置。事件驱动的方式将迫使你将代码放在它应该在的地方--它仅应该在的地方。如果你在同一个方法中执行数据库调用和更新UI组件,那么你就在一个类中写入了太多的逻辑。分析你系统中的事件,创建底层的事件模型将迫使你将代码放到正确的地方。将费时的数据库调用代码放在非UI类中,也不要在非UI组件中更新UI组件。采用事件驱动的体系,UI负责UI更新,数据库管理类负责数据库调用。在这一点上,每一个封装的类都只用关心自己的线程,不用担心系统其它部分如何动作。当然,设计、构建一个事件驱动的客户端也很有用,但是需要花费的时间代价远超过带来的结果系统的灵活性和可维护性的提高。

 
共6页。 9 1 2 3 4 5 6

软件资讯·软件下载尽在天极软件

共6页。 首页 上一页 2 3 4 5 6
相关搜索:
相关文章及软件
关注此文读者还看过
热门关注
特别推荐
网友关注
软件下载
娱乐下载
驱动下载
文章排行
本周
本月
最近更新
关于我们|About us|网站律师|天极服务|电子杂志|RSS订阅|加入我们|网站地图
TMG
Copyright (C) 1999-2009 Chinabyte.com, All Rights Reserved 版权所有 天极网络
商务联系、网站内容、合作建议:010-82657868
版权声明 在线提交意见反馈 渝ICP证B2-20030003号
经营性网站备案信息 网警备案 中国网站排名
天极传媒:天极网|比特网|IT专家网|IT商网|52PK游戏网|IT分众