使用swingworker

上传人:j****9 文档编号:47010776 上传时间:2018-06-29 格式:DOC 页数:21 大小:778KB
返回 下载 相关 举报
使用swingworker_第1页
第1页 / 共21页
使用swingworker_第2页
第2页 / 共21页
使用swingworker_第3页
第3页 / 共21页
使用swingworker_第4页
第4页 / 共21页
使用swingworker_第5页
第5页 / 共21页
点击查看更多>>
资源描述

《使用swingworker》由会员分享,可在线阅读,更多相关《使用swingworker(21页珍藏版)》请在金锄头文库上搜索。

1、使用 SwingWorker 之一(2007-01-27 19:18:16)正确理解和使用 Swing 线程模型编程是编写响应灵活的 Swing 程序的关键。从 Java SE 6 开始引进的 SwingWorker 能帮你轻松的编写多线程 Swing 程序,改善你 Swing 程序的结构,提高界面响应的灵活性。SDN(Sun developer Network)上有一篇很好的文章: Improve Application Performance With SwingWorker in Java SE 6 详细演示了如何使 用 SwingWorker 改善 Swing 应用程序。把它翻译过来同

2、大家共享。 摘要摘要桌面应用程序员常见的错误是误用 Swing 事件调度线程(Event Dispatch Thread, EDT)。他们要么从非 UI 线程访问 UI 组件,要么不考虑事件执行顺序,要么不使用独立任 务线程而在 EDT 线程上执行耗时任务,结果使编写的应用程序变得响应迟钝、速度很慢。 耗时计算和输入/输出(IO)密集型任务不应放在 Swing EDT 上运行。发现这种问题的代码并 不容易,但 Java SE 6 提供了 javax.swing.SwingWorker 类,使修正这种代码变得更容易。本文演示了一个使用 SwingWorker 类创建和管理任务线程的例子,描述了如

3、何避 免编写运行缓慢、感觉迟钝、容易失去响应的用户界面。这个演示例子叫 Image Search, 它展示了如何使用 SwingWorker API 来和网站 Flickr 进行交互、搜索并下载图像。如果需要理解 Swing Ui 的基本概念,包括事件处理和侦听等 UI 编程,可以参照 前面的文章,或从 Sun 官方网站下载阅读 Java 教程的 Swing 部分。 演示程序介绍演示程序介绍Image Search 执行的耗时任务是访问 Flickr 网站服务,该任务不应该在 EDT 上 执行。Image Search 程序搜索 Flickr 站点,搜索匹配用户输入的查询条件的图像,下载 匹配

4、图形的缩略图。当用户从缩略图列表中选择某缩略图时,它将下载该图的原始图片。 该演示程序使用 SwingWorker 类作为任务线程,从而避免了在 EDT 上执行这些耗时任务。当用户输入查询条件时,程序在 Flickr 网站请求一个图像查询。如果有符合查询 条件的图像,程序下载上限为 100 个的缩略图像。可以修改程序改变下载图像的数目。搜 索和下载图像的同时,有一进度条显示搜索进度。图 1 显示了查询字段和进度条:图 1,搜索图像并显示下载进度每当程序成功下载一个缩略图片后,就添加到一个 JList 组件中,图片从 Flickr 站点到达后就被添加列表中。程序使用 SwingWorker 的一

5、个实例,程序能在每个图片到达 时添加到列表,而不用等待所有的图片都到达。图 2 显示列表中的图片:图 2 匹配缩略图的列表当从列表选择一个图片,程序将下载该图片的原始图片,并显示在列表的下面。 当大图片下载时,另一进度条将显示下载进度。图 3 显示列表和图片下载进度条。图 3 选中缩略图下载大图片最后,当所有图片数据下载完毕后,程序在列表下方显示图片。程序使用 SwingWorker 来完成所有图片搜索和下载任务。另外,程序还演示了如 何取消任务,如何在任务完成之前获得即时结果。该程序有两个 SwingWorker 的子类: ImageSearcher 和 ImageRetriever。Ima

6、geSearcher 类负责搜索和获取图片列表中的缩略 图,ImageRetriever 类负责用户从列表选择时下载原始版本的图片。本文用这个类来描述 SwingWorker 类的主要功能。图 4 显示程序的整个外观。图 4 使用 SwingWorkere 类创建响应灵活程序界面回顾回顾 SwingSwing 线程基础线程基础一个 Swing 程序中一般有下面三种类型的线程:* 初始化线程(Initial Thread)* UI 事件调度线程(EDT)* 任务线程(Worker Thread)每个程序必须有一个 main 方法,这是程序的入口。该方法运行在初始化或启动线 程上。初始化线程读取程

7、序参数并初始化一些对象。在许多 Swing 程序中,该线程主要目 的是启动程序的图形用户界面(GUI)。一旦 GUI 启动后,对于大多数事件驱动的桌面程序来说,初始化线程的工作就结束了。Swing 程序只有一个用 EDT,该线程负责 GUI 组件的绘制和更新,通过调用程序的 事件处理器来响应用户交互。所有事件处理都是在 EDT 上进行的,程序同 UI 组件和其基本数据模型的交互只允许在 EDT 上进行,所有运行在 EDT 上的任务应该尽快完成,以便 UI 能 及时响应用户输入。Swing 编程时应该注意以下两点: 1.从其他线程访问 UI 组件及其事件处理器会导致界面更新和绘制错误。 2.在

8、EDT 上执行耗时任务会使程序失去响应,这会使 GUI 事件阻塞在队列中得不到处理。 3.应使用独立的任务线程来执行耗时计算或输入输出密集型任务,比如同数据库通信、访 问网站资源、读写大树据量的文件。总之,任何干扰或延迟 UI 事件的处理只应该出现在独立任务线程中;在初始化线 程或任务线程同 Swing 组件或其缺省数据模型进行的交互都是非线程安全性操作。SwingWorker 类帮你管理任务线程和 Swing EDT 之间的交互,尽管 SwingWorker 不能解决并发线程中遇到的所有问题,但的确有助于分离 Swing EDT 和任务线程,使它们 各负其责:对于 EDT 来说,就是绘制和更

9、新界面,并响应用户输入;对于任务线程来说, 就是执行和界面无直接关系的耗时任务和 I/O 密集型操作。 使用合适线程使用合适线程初始化线程运行程序的 main 方法,该方法能处理许多任务。但在典型的 Swing 程 序中,其主要任务就是创建和运行应用程序的界面。创建 UI 的点,也就是程序开始将控制 权转交给 UI 时的点,往往是同 EDT 交互出现问题的第一个地方。Image Search 示例的主类是 MainFrame,从其 main 方法启动。许多程序使用下面 方法启动界面,但这是错误的启动 UI 界面的方法:public class MainFrame extends javax.s

10、wing.JFrame .public static void main(String args) new MainFrame().setVisible(true); 尽管这种错误出现在开始,但仍然违反了不应在 EDT 外的其他线程同 Swing 组件 交互的原则。这个错误尤其容易犯,线程同步问题虽然不是马上显示出来,但是还要注意 避免这样书写。正确启动 UI 界面应该如下:public class MainFrame extends javax.swing.JFrame .public static void main(String args) SwingUtilities.invokeLa

11、ter(new Runnable() public void run() new MainFrame().setVisible(true);); 使用 NetBeans IDE 的开发者应该对这段代码很熟悉,NetBeans 通常会自动生成 这段代码。这段启动代码虽然和 SwingWorker 没有直接关系,但是这个编程范式很重要。SwingUtilities 类包含一些静态方法帮你同 UI 组件交互,其中 invokeLater 方法意思是 在 EDT 上执行其 Runnable 任务。Runnable 接口定义了可作为独立线程执行的任务。在初始化线程中使用 invokeLater 方法能正

12、确的初始化程序界面。就像前面文章所提到的,此方法是异步执行的,也就是说调用会立即返回。创建界面后,大部分初始化 线程基本上就结束了。通常有两种办法调用此方法:* SwingUtilities.invokeLater* EventQueue.invokeLater两个方法都是正确的,选择任何一个都可以。实际上,SwingUtilities 版只是一 个薄薄的封装方法,它直接转而调用 EventQueue.invokeLater。因为 Swing 框架本身经常 调用 SwingUtilities,使用 SwingUtilities 可以减少程序引入的类。另种将任务放到 EDT 执行的方法是 Swi

13、ngUtilities.invokeAndWait,不像 invokeLater,invokeAndWait 方法是阻塞执行的,它在 EDT 上执行 Runnnable 任务,直到 任务执行完了,该方法才返回调用线程。invokeLater 和 invokeAndWait 都在事件派发队列中的所有事件都处理完之后才 执行它们的 Runnable 任务,也就是说,这两个方法将 Runnable 任务放在事件队列的末尾。注意:虽然可以在其他线程上调用 invokeLater,也可以在 EDT 上调用 invokeLater,但是千万不要在 EDT 线程上调用 invokeAndWait 方法!很容

14、易理解,这样做 会造成线程竞争,程序就会陷入死锁。将将 EDTEDT 线程仅用于线程仅用于 GUIGUI 任务任务Swing 框架负责管理组件绘制、更新以及 EDT 上的线程处理。可以想象,该线程 的事件队列很繁忙,几乎每一次 GUI 交互和事件都是通过它完成。事件队列的上任务必须 非常快,否则就会阻塞其他任务的执行,使队列里阻塞了很多等待执行的事件,造成界面 响应不灵活,让用户感觉到界面响应速度很慢,使他们失去兴趣。理想情况下,任何需时 超过 30 到 100 毫秒的任务不应放在 EDT 上执行,否则用户就会觉察到输入和界面响应之间 的延迟。幸运的是,不会仅仅因为有复杂的任务、计算或输入输出

15、密集任务需要作为 GUI 事件处理任务执行,Swing 的性能就要有所降低。毕竟有许多桌面程序执行耗时任务,比 如处理电子表格公式、跨越网络查询数据库、通过 Internet 向其他程序发送信息。即使有 这些任务,界面仍然可以让用户感觉到响应灵活、快捷。编写响应灵活的程序需要创建和 管理独立于 EDT 的线程。在 Image Search 程序中,有两个事件如果完全在 EDT 上处理就会降低界面的响应 速度:图像搜索处理和选中图片下载处理。两个事件处理都要访问 Web 服务,这些服务通常要许多秒后才能响应,在此期间, 如果程序在 EDT 上进行 Web 服务交互,用户就不能取消搜索或者同界面交

16、互,像这两种都不应该在 EDT 上运行。图 5 显示了在 A 和 B 点之间,EDT 不能处理 UI 事件,AB 两点之间代表了程序访问 Flickr 网站 Web 服务的 IO 操作时间:图 5. 在执行 Web 服务期间 EDT 不能响应 UI 事件javax.swing.SwingWorker 类是 Java SE 6 中新出现的类,使用 SwingWorker,程 序能启动一个任务线程来异步查询,并马上返回 EDT 线程。图 6 显示了使用 SwingWorker 后,事件处理立即返回,允许 EDT 继续执行后续的 UI 事件。图 6.使用任务线程,程序能够在避免在 EDT 上执行 I/O 密集型任务使用 SwingWorker 之二(2007-01-29 10:04:40)转载分类: SwingSwingWorkerSwingWorker 基础基础本节简要介绍 SwingWorker 的功能。SwingWorker 的定义如下:public abstract class SwingWorker extends Object imple

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 中学教育 > 初中教育

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号