SwingWorker是Java SE 6.0新加入的一个工具包,利用它可以使长时间运行并更新用户界面的任务大大简化。本文以一个异步加载JTree的demo演示了SwingWorker的基本功能。
环境准备
运行demo
- 从附件中下载asynch_load_tree.zip到本地并解压。
- NetBeans主菜单依次选择“文件”——“打开项目”。
- 在弹出的“打开项目”对话框中选择刚才解压之后的asynch_load_tree目录,点击“打开项目”按钮。
- 在“文件”视图中找到asynch_load_tree项目下的init_schema_and_data.sql,按照下图步骤操作。
- 在“项目”视图中找到asynch_load_tree项目,在上下文菜单中选择“运行”项。
- 按照下图操作,看一下在EDT
中执行耗时阻塞任务的严重后果。
EDT是啥米呀
在Java中,键盘输入、鼠标点击或者应用程序本身产生的请求会被封装成一个事件,放进一个事件队列中,java.awt.EventQueue对象负责从这个队列中取出事件并派发它们。而EventQueue的派发有一个单独的线程管理,这个线程叫做事件派发线程(Event Dispatch Thread),也就是EDT。此外,Swing的绘制请求也是通过EDT来派发的。
根据以上这两个事实,我们就可以解释刚才demo中发生的事情。当checkbox被选中之后,再双击根结点,触发了以下的程序:
public void treeExpanded(TreeExpansionEvent event) {
long handleTime = readHugeData();
label.setText("处理时间为" + handleTime);
}
事实上,在demo中是用Thread.sleep()方法来模拟readHugeData这个从数据库中读取大量记录这个阻塞方法。那么在这种情况下,EDT在等待数据库的返回期间是不能接收任何事件(比如键盘输入),也不能处理任何组件的绘制。
解决的方法是什么呢?很容易想到,把耗时的方法从EDT中剥离出来,放到单独的工作线程中执行。例如下面这样:
public void treeExpanded(TreeExpansionEvent event) {
new Thread(new Runnable() {
public void run() {
long handleTime = readHugeData();
label.setText("处理时间为" + handleTime);
}
}).start();
}
很遗憾,这段代码违反了Swing的单线程原则:即没有在EDT上,而是在工作线程里修改这个label的状态。根据SUN的说法,在测试时可能没问题,但死锁可能随时出现,而且多半发生在给老板演示的时候:>
在SwingWorker出现之前的解决方法是javax.swing.SwingUtilities类的invokeLater方法。在上面的代码片断中,只需将更新label状态的工作封装成一个Runnable的示例,然后作为参数传递给invokeLater()就好了:
public void treeExpanded(TreeExpansionEvent event) {
new Thread(new Runnable() {
public void run() {
final long handleTime = readHugeData();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
label.setText("处理时间为" + handleTime);
}
});
}
}).start();
}
这样就可以保证demo可以平稳和正确地运行了,但是,要创建好多匿名的Runnable,导致代码难于阅读和维护。为了简化与EDT的交互,SwingWorker登场了。
SwingWorker入门
这个demo中涉及的只是SwingWorker最基础的东东,所以不必担心。看看如何使用把:
public void treeExpanded(TreeExpansionEvent event) {
new SwingWorker<Long, Void>() {
@Override
protected Long doInBackground() {
return readHugeData();
}
@Override
protected void done() {
label.setText("处理时间为" + get());
}
}.execute();
}
我们把耗时阻塞任务放到doInBackground()方法中,更新组件状态的任务放到done()方法中。当任务完成后,SwingWorder自动调用EDT中的done()方法。此外在done()方法中,可以调用get()方法获取doInBackground()方法的返回值,在demo中这个返回值是任务处理时长。好了,SwingWorker就讲到这里了。什么,那个new SwingWorker<Long, Void>()中第二个泛型类型Void是啥意思?请参考Improve Application Performance With SwingWorker in Java SE 6
这篇牛文。
demo的其他细节
关于如何自定义TreeNode类、怎样初始化JTree、异步读取所有子结点等问题。还是请看代码把,人家很用心写了注释的说。。。
- 大小: 47.3 KB
- 大小: 23.4 KB
分享到:
相关推荐
本文介绍了修订过的SwingWorker类,并演示了和基于模型的组件(model-based components)如JTable和JTree同时使用线程。 要理解本文呈现的材料,熟悉SwingWorker和JTable和JTree组件会有所帮助。你可以在存档索引中...
swing swingworker wingworker wingworker
主要介绍了在Java的Swing编程中使用SwingWorker线程模式及顶层容器的方法,适用于客户端图形化界面软件的开发,需要的朋友可以参考下
Swt一般情况不允许在另外一个线程中更新控件内容,此程序使用java swing的SwingWorker对swt的控件进行操作更新。对于喜欢使用SwingWorker更新Swing控件的人来说,也可以使用SwingWorker更新Swt控件
Swing线程的深入理解和SwingWorker基础知识介绍[参照].pdf
北京火龙果软件工程技术中心原文来自java.sun.com作者:JosephBowbeer本文并不属于任何系列,但它是...本文介绍了修订过的SwingWorker类,并演示了和基于模型的组件(model-basedcomponents)如JTable和JTree同时使
Swing线程的深入理解和SwingWorker基础知识介绍
作业:完善swingworker排序功能
北京原文来自java.sun.com作者:JosephBowbeer本文并不属于任何系列,但它是TheSwingConnection中发表的...本文介绍了修订过的SwingWorker类,并演示了和基于模型的组件(model-basedcomponents)如JTable和JTree同时使
SwingWorker的替代品,用于在Swing中执行异步任务。 我们将SwingWorker.java与Action接口合并,生成AbstractAsynchronousAction.java。 此类的具体扩展可以用来代替任何Action。
NULL 博文链接:https://chenhailong.iteye.com/blog/1312202
带有 ImageIcons 的 JLabes 用于显示图像、用于用户界面的 JButton 和 FileChooser、用于异步图像处理的 SwingWorker(技术上来自实用程序库)以及其他一些。 虽然每件事都运行顺利,但架构充其量是随意的(我在...
要通过修改代码来使用AnalysisWorker ,看到里面的代码注释SimpleApp的上单击处理程序analyzeButton 。 您只需要注释掉try-catch块并取消注释工作代码即可。 此外,该解决方案还需要: 处理从工作程序内部抛出的...
Future接口是Java线程Future模式的实 现,可以来进行异步计算。 Future模式可以这样来描述:我有一个任务,提交给了Future,Future替我完成这个任务。期间我自己可以去做任何想做的事情。一段时 间之后,我就便...
Exceptionin thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/jdesktop/swingworker/SwingWorker at com.android.draw9patch.Application$1.run(Application.java:48) at java.awt.event....
使用JProgressBar和SwingWorker做的Java进度条 简单方便 效果看这里:http://blog.csdn.net/kakashi8841/archive/2011/05/03/6388797.aspx
运用javax.swingworker类生成DynamicJButton示例
Swing MVC 观察者 系统托盘 SwingWorker 电子相册
不确定某个程序运行多久,用进度条来监测,如果进度条监测到运行结果结束了,就退出进度条,否则以一种不确定的状态等待。