使用SwingWorker异步加载JTree
SwingWorker是Java SE 6.0新加入的一个工具包,利用它可以使长时间运行并更新用户界面的任务大大简化。本文以一个异步加载JTree的demo演示了SwingWorker的基本功能。
环境准备
软件或资源 | 要求的版本 |
Java Development Kit (JDK) | 6.0(5.0需要自行加入swingworker到classpath) |
NetBeans IDE | 6.5 |
Java DB | 10.4.1.3 - (648739) |
运行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、异步读取所有子结点等问题。还是请看代码把,人家很用心写了注释的说。。。
- asynch_load_tree.zip (14.5 KB)
- 下载次数: 757
使用SwingWorker异步加载JTree的更多相关文章
- winform异步加载数据到界面
做一个学习记录. 有两个需求: 1.点击按钮,异步加载数据,不卡顿UI. 2.把获取的数据加载到gridview上面. 对于需求1,2,代码如下: public delegate void ShowD ...
- 【Android】纯代码创建页面布局(含异步加载图片)
开发环境:macOS 10.12 + Android Studio 2.2,MinSDK Android 5.1 先看看总体效果 本示例是基于Fragment进行的,直接上代码: [界面结构] 在 F ...
- 【代码笔记】iOS-实现网络图片的异步加载和缓存
代码: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. se ...
- 使用jOrgChart插件, 异步加载生成组织架构图
jOrgChart插件是一个用来实现组织结构图的Jquery的插件- 一.特点 1.支持拖拽修改子节点: 2.支持节点缩放展示: 3.方便修改css定义样式: 4.超轻量型: 5.兼容性好,基本支持所 ...
- 向上滚动或者向下滚动分页异步加载数据(Ajax + lazyload)[上拉加载组件]
/**** desc : 分页异步获取列表数据,页面向上滚动时候加载前面页码,向下滚动时加载后面页码 ajaxdata_url ajax异步的URL 如data.php page_val_name a ...
- Android-Universal-Image-Loader 图片异步加载类库的使用
在博客中看到一篇利用组件进行图片异步加载的文章在此作记录 原文:http://blog.csdn.net/vipzjyno1/article/details/23206387 这个图片异步加载并缓存的 ...
- 淘宝购物车页面 智能搜索框Ajax异步加载数据
如果有朋友对本篇文章的一些知识点不了解的话,可以先阅读此篇文章.在这篇文章中,我大概介绍了一下构建淘宝购物车页面需要的基础知识. 这篇文章主要探讨的是智能搜索框Ajax异步加载数据.jQuery的社区 ...
- Android开发--异步加载
因为移动端软件开发思维模式或者说是开发的架构其实是不分平台和编程语言的,就拿安卓和IOS来说,他们都是移动前端app开发展示数据和用户交互数据的数据终端,移动架构的几个大模块:UI界面展示.本地数据可 ...
- JS -- 异步加载进度条
今天在博客园问答里面看到博友问道怎么实现Ajax异步加载产生进度条. 很好奇就自己写了一个. 展现效果: 1) 当点击Load的时候,模拟执行异步加载. 浏览器被遮挡. 进度条出现. 实现思路: 1. ...
- iframe异步加载技术及性能
我们会经常使用iframes来加载第三方的内容.广告或者插件.使用iframe是因为它可以和主页面并行加载,不会阻塞主页面.当然使用iframe也是有利有弊的:Steve Souders在他的blog ...
随机推荐
- 8.18域横向smb&wmi明文或hash传递
知识点 windows 2012以上版本默认关闭wdigust,攻击者无法从内存中获取明文密码: Windows2012以下版本如安装KB287199补丁,同样也无法从内存中获取明文密码: 解决方法: ...
- FFmpeg开发笔记(五十二)移动端的国产视频播放器GSYVideoPlayer
GSYVideoPlayer是一个国产的移动端视频播放器,它采用了IJKPlayer.Media3(EXOPlayer).MediaPlayer.AliPlayer等四种播放器内核,支持弹幕.滤镜. ...
- C++:使自定义类支持迭代器
概述 在 C++ 中,链表迭代器是一种用来遍历链表(如 std::list)元素的工具.链表是一种数据结构,其中每个元素(节点)包含一个数据值和一个指向下一个节点的指针.链表迭代器允许以类似于数组的方 ...
- Python网页应用开发神器Dash 2.18.1稳定版本来啦
本文示例代码已上传至我的Github仓库:https://github.com/CNFeffery/dash-master Gitee同步仓库地址:https://gitee.com/cnfeffer ...
- JavaScript Library – Swiper
前言 官网已经有很好的教程了, 这篇只是记入一些我用过的东西和冷门知识. 参考 官网安装 官网 Demo 安装 yarn add swiper JS import Swiper from 'swipe ...
- OpenSSL证书通过Subject Alternative Name扩展字段扩展证书支持的域名
1.概述 1.1 什么是Subject Alternative Name(证书主体别名) SAN(Subject Alternative Name) 是 SSL 标准 x509 中定义的一个扩展.它允 ...
- SaaS架构:流程架构分析
大家好,我是汤师爷~ 今天聊聊SaaS架构中的流程架构分析. 业务流程的概念 业务流程是企业为实现目标而制定的一套系统化的工作方法.它由一系列有序的业务活动组成,按照既定规则将资源(输入)转化为有价值 ...
- Unity中的光源类型(向前渲染路径进行光照计算)
Unity中的光源类型 Unity中共支持4种光源类型: 平行光 点光源 聚光灯 面光源(在光照烘焙时才可以发挥作用) 光源的属性: 位置 方向(到某个点的方向) 颜色 强度 衰减(到某个点的衰减) ...
- logisim学习感想(持续更新)
状态机类型 存在两种类型的状态机,分别为mealy型状态机和moore型状态机,在实验中,二者的大体实现如下: 其中从输入到输出的连线只有mealy状态机才有,而moore型则无此线. 区分两种类型的 ...
- 使用 Ant-Design-Vue 制作一个带图片上传功能的表单对话框
功能需求 使用 Antdv 的 Modal 组件内嵌一个 a-form 表单,具有添加数据和图片的功能. 页面结构设计 <template> <!--Modal--> < ...