Java开发中的线程安全选择与Swing - 编程入门网
Java开发中的线程安全选择与Swing时间:2011-01-24Swing API的设计目标是强大、灵活和易用。特别地,我们希望能让程序员们方便地建立新的Swing组件,不论是从头开始还是通过扩展我们所提供的一些组件。 出于这个目的,我们不要求Swing组件支持多线程访问。相反,我们向组件发送请求并在单一线程中执行请求。 本文讨论线程和Swing组件。目的不仅是为了帮助你以线程安全的方式使用Swing API,而且解释了我们为什么会选择现在这样的线程方案。 本文包括以下内容: ◆单线程规则:Swing线程在同一时刻仅能被一个线程所访问。一般来说,这个线程是事件派发线程(event-dispatching thread)。 ◆规则的例外:有些操作保证是线程安全的。 ◆事件分发:如果你需要从事件处理(event-handling)或绘制代码以外的地方访问UI,那么你可以使用SwingUtilities类的invokeLater()或invokeAndWait()方法。 ◆创建线程:如果你需要创建一个线程——比如用来处理一些耗费大量计算能力或受I/O能力限制的工作——你可以使用一个线程工具类如SwingWorker或Timer。 为什么我们这样实现Swing:我们将用一些关于Swing的线程安全的背景资料来结束这篇文章。 Swing的规则是: 一旦Swing组件被具现化(realized),所有可能影响或依赖于组件状态的代码都应该在事件派发线程中执行。 这个规则可能听起来有点吓人,但对许多简单的程序来说,你用不着为线程问题操心。在我们深入如何撰写Swing代码之前,让我们先来定义两个术语:具现化(realized)和事件派发线程(event-dispatching thread)。 具现化的意思是组建的paint()方法已经或可能会被调用。一个作为顶级窗口的Swing组件当调用以下方法时将被具现化:setVisible(true)、show()或(可能令你惊奇)pack()。当一个窗口被具现化,它包含的所有组件都被具现化。另一个具现化一个组件的方法是将它放入到一个已经具现化的容器中。稍后你会看到一些对组件具现化的例子。 事件派发线程是执行绘制和事件处理的线程。例如,paint()和actionPerformed()方法会自动在事件派发线程中执行。另一个将代码放到事件派发线程中执行的方法是使用SwingUtilities类的invokeLater()方法。 所有可能影响一个已具现化的Swing组件的代码都必须在事件派发线程中执行。但这个规则有一些例外: 有些方法是线程安全的:在Swing API的文档中,线程安全的方法用以下文字标记: This method is thread safe, although most Swing methods are not. (这个方法是线程安全的,尽管大多数Swing方法都不是。) 一个应用程序的GUI常常可以在主线程中构建和显示:下面的典型代码是安全的,只要没有(Swing或其他)组件被具现化: public class MyApplication{ public static void main(String[] args) {JFrame f = new JFrame("Labels"); // 在这里将各组件// 加入到主框架……f.pack();f.show();// 不要再做任何GUI工作…… }} Java开发中的线程安全选择与Swing(2)时间:2011-01-24上面所示的代码全部在“main”线程中运行。对f.pack()的调用使得JFrame以下的组件都被具现化。这意味着,f.show()调用是不安全的且应该在事件派发线程中执行。尽管如此,只要程序还没有一个看得到的GUI,JFrame或它的里面的组件就几乎不可能在f.show()返回前收到一个paint()调用。因为在f.show()调用之后不再有任何GUI代码,于是所有GUI工作都从主线程转到了事件派发线程,因此前面所讨论的代码实际上是线程安全的。 一个applet的GUI可以在init()方法中构造和显示:现有的浏览器都不会在一个applet的init()和start()方法被调用前绘制它。因而,在一 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |