浴兰节已过,粽叶留香, 借苏东坡词为祭
浣溪沙 苏轼
轻汗微微透碧纨。明朝端午浴芳兰。流香涨腻满晴川。
彩线轻缠红玉臂,小符斜挂绿云鬟。佳人相见一千年。
--------------------分割线在此,谁敢动我--------------------------------------------------------------------------------------------
之前使用SWT来开发GUI桌面小应用程序,牵涉数据库,报表等等东西,刚开始,关于这方面的经验尚浅,跌跌撞撞的写下去。
一. 第一个问题: UI僵住 / UI假死
程序很快就写出来了(借助了SWT Designer之便,呵呵),可惜运行时老是感觉怪怪的,不是很舒服,哪里不舒服也说不上来,后来多运行几遍才发现问题:
每次连接数据库,导出报表的时候,UI就僵住了,点两下,程序就华丽丽地“没有响应”了。
到这时俺这么傻大概也明白了:
UI操作和数据库查询都在UI线程里,而数据库执行查询的时间太长,这个UI线程假死了。
原因明白,解决方法也就出来了:
分开UI线程和逻辑处理线程(比较费时间的运算,例如:数据库查询)。
不废话上Sample Code (俺只上简要代码,对不住兄弟们了,大家都懂的):
Thread thread = new Thread(new Runnable() {
public void run() {
// TODO 长时间的运算
while (!display.isDisposed()) {
...
...
...
}
};
};);
thread.start();
测试运行:
连接数据库,查询,导出报表的时候,UI依然可以被拖动(当然,为了防止此时用户再次点击按钮来查询数据库,我们应该将UI上的一些元素disable掉,这个大家也懂的)---------沾沾自喜(福兮祸之所出)
二 Java OutOfMemory(果不其然,出问题了)
上面修改后的代码,自以为正确,结果还是出问题了,连续多次导出报表后,我发现UI又死了,这回不是假死,而是真死了----OutOfMemory。
百思不得其解,于是乎借助Jprofiler工具,发现每导出一次报表,其内存就会增长一次,从2Mb--->60Mb,然后就Runtime Error:OutOfMemory了。
通过Jprofiler的内存分析,可以排除UI的问题因素,所以问题肯定出在连接数据库并导出报表的逻辑处理线程(就是上面new 的Thread)上,应该是线程关闭时不能及时释放资源。
我仔细查了下,发现导出报表过程中我创建的文件流或者缓冲流等等都正常关闭了,没有占用资源不释放的地方。最后折腾了半天,终于定位到问题点:"静态调用外部类TransformerFactory来解析xml"-----解析时占用的内存在解析后没有立即被释放(原因不是很清楚,难道是DOM的关系???),由于这个原因:每次new Thread导出报表之后资源都得不到立即释放,而且我们知道线程间是不能共享内存的(独占性),于是系统可用内存越来越少,导致最终的OutOfMemory。
解决方案:
由于不了解TransformerFactory如何释放资源,所以我采用了另外一种折衷方案:仅使用一个全局的Thread(逻辑处理线程)来导出报表,当TransformerFactory多次解析xml时,它最多占用当前逻辑处理线程所分配的内存块,而不会像之前那样每次new Thread并占用一个新的内存块(当然也可以用线程池,我这里一个线程就可以完全满足需求了,故不需要使用线程池)。
唯一注意点:因为目前仅有一个逻辑处理线程,所以该逻辑处理线程也和UI线程一样,在一开始就被启动并处于监听状态。
private Thread thread;
public static void main(final String[] args) {
display = Display.getDefault();
shell = new Shell(display, SWT.DIALOG_TRIM | SWT.MIN | SWT.CLOSE);
thread = new Thread(new Runnable() {
public void run() {
// TODO 长时间的运算
while (!display.isDisposed()) {
if ("导出报表按钮被点击") {
...
...
...
}
}
};
};);
//使线程处于就绪状态
thread.start();
}
测试:
经过多次导出报表的测试,终于发现OK了,长出一口气。
三 UI未操作时,CPU占用率比较高,几乎100%
上面的代码导出报表是没问题了,但是在不做任何操作时, CPU占用率非常高,几乎100%.立刻判断出:逻辑处理线程出问题了,而且可以肯定是该线程一直处于监听状态所致。Jprofiler也证明了这点。
解决方法:
在不点击报表按钮时,让该线程sleep
private Thread thread;
public static void main(final String[] args) {
display = Display.getDefault();
shell = new Shell(display, SWT.DIALOG_TRIM | SWT.MIN | SWT.CLOSE);
thread = new Thread(new Runnable() {
public void run() {
// TODO 长时间的运算
while (!display.isDisposed()) {
if ("导出报表按钮被点击") {
...
...
...
} else {
// 如果未点击创建报表按钮,则创建报表的线程Sleep中
try {
Thread.sleep(1000);
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
};
};);
//使线程处于就绪状态
thread.start();
}
测试:
总算是OK了, 打开UI不做操作时或者时导出报表完毕之后,CPU的占用率都是0%。
-----------
小记:
虽然只是写了个简单的桌面应用程序,但是依旧可以发现很多问题----不经过完全测试的软件是可怕而且不可信的;
思考和解决问题也是一种成长------程序员的快乐难道建立在此?
与大家一起分享和成长。。。
分享到:
相关推荐
该软件是一个基于java语言的socket编程,可以实现单个服务器对应多个客户端的聊天。采用swt,功能还是比较完善的。
Java核心编程:流、多线程、实体类、集合类、正则表达式、XML、属性文件。Java图形编程:AWT(Java2D、JavaSound、Media)、Swing、SWT、Jface。Java网络编程:Applet、Socket/TCP/UDP、NIO、RMI、CORBA。Java高级...
javathread.zip 10.Java多线程编程(线程池、生产者消费者、存取款实例) javautil.zip 11.Java常用实体类 javaxml.zip 14.XML属性文件 第4部分(6个程序包) javagui.zip 15.Java GUI库对比实例 javaawt.zip ...
javathread.zip 10.Java多线程编程(线程池、生产者消费者、存取款实例) javautil.zip 11.Java常用实体类 javaxml.zip 14.XML属性文件 第4部分(6个程序包) javagui.zip 15.Java GUI库对比实例 javaawt.zip 16....
java入门类,上百这种格式java源程序,包括swt,多线程,网络编程。不要积分吧,方便大家交流资源!
Java核心编程:流、多线程、实体类、集合类、正则表达式、XML、属性文件。Java图形编程:AWT(Java2D、JavaSound、Media)、Swing、SWT、Jface。Java网络编程:Applet、Socket/TCP/UDP、NIO、RMI、CORBA。Java高级...
Java核心编程:流、多线程、实体类、集合类、正则表达式、XML、属性文件。Java图形编程:AWT(Java2D、JavaSound、Media)、Swing、SWT、Jface。Java网络编程:Applet、Socket/TCP/UDP、NIO、RMI、CORBA。Java高级...
Java核心编程:流、多线程、实体类、集合类、正则表达式、XML、属性文件。Java图形编程:AWT(Java2D、JavaSound、Media)、Swing、SWT、Jface。Java网络编程:Applet、Socket/TCP/UDP、NIO、RMI、CORBA。Java高级...
Java核心编程:流、多线程、实体类、集合类、正则表达式、XML、属性文件。Java图形编程:AWT(Java2D、JavaSound、Media)、Swing、SWT、Jface。Java网络编程:Applet、Socket/TCP/UDP、NIO、RMI、CORBA。Java高级...
javathread.zip 10.Java多线程编程(线程池、生产者消费者、存取款实例) javautil.zip 11.Java常用实体类 javaxml.zip 14.XML属性文件 第4部分(6个程序包) javagui.zip 15.Java GUI库对比实例 javaawt.zip ...
程序是数据结构中马踏棋盘的一种改进方法,并且用多线程方法实现过程演示,界面采用SWT编程。
splash.zip 通过自己的线程在Splash对话框中显示文字(136KB)<END><br>6,res_dlg.zip 大小可调的对话框(21KB)<END><br>7,splitter.zip 可变的分割视图(58KB)<END><br>8,anicon1.zip 在窗口的标题条上显示...
12.1.5 为什么需要多线程309 12.1.6 线程分类309 12.2 线程的生命周期309 12.2.1 线程的状态及转换310 12.2.2 线程睡眠311 12.2.3 线程让步313 12.2.4 线程的加入313 12.3 线程的调度和优先级314 12.4 线程的同步315...
Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...
Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...
Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...