部门刚成立,开发的产品也才刚刚进入迭代四,还有很多工具不够完善。
前几天定位一个问题,测试人员发送过来大量的日志,打开一看发现其中大部分都是无关的打印,于是很痛苦的使用各种关键字去搜寻自己想要的东西;更加悲剧的是,当想回过头看看刚查找到的日志时,又只能使用搜索的上一个来跳转。问题虽然弄清楚了,但人也看晕了。于是想自己弄个日志查看的东西。回家大致写出来了,但有个问题却怎么也调不好。
在读取模块中,先要对读取的文件的每一行进行处理,判断它是否符合当前的筛选条件,然后再将它按照日志的等级,在一个JTextPane中进行显示。
一开始就想到了使用SwingWorker来实现,然后就采取了以下的方法:
protected Void doInBackground() throws Exception { BufferedReader reader = null; reader = new BufferedReader(new FileReader(file)); String line = ""; while ((line = reader.readLine()) != null) { if (!cache.isSatisfy(line)) { continue; } publish(line); } reader.close(); return null; } protected void process(List<String> list) { for (String line : list) { if (line.trim().equals("")) { continue; } char ch = line.charAt(16);// 日志的等级第一个字母 switch (ch) { case 'D': { textPane.debug(line); break; } case 'I': { textPane.info(line); break; } case 'E': { textPane.error(line); break; } default: { textPane.warn(line); break; } } } }
即在doInBackground方法中读取文件,然后判断其是否满足条件,将满足条件的publish到process中,再显示到textPane中去。
当然同时还有一个进度条;原本以为这样就可以了:进度条在不断的转动,表明读取过程在继续;后台数据不断的在处理;
但实际上,运行的时候却发现进度条最开始还动一下,读到后来界面却死了。
测了一下,发现是由于读文件、判断条件是否满足速度很快,但将数据加到TextPane中去的速度却稍微慢些——但实际上也不慢,这导致了写到界面上去的速度很快,从而使得界面出现假死的现象。如果数据读取的速度慢些,速度条应该是可以正常工作的。于是在doInBackground中每处理一条数据后休眠了一下,进度条正常了,但处理时间却大大增加,经过调整,在5ms休眠1ms的时候能够达到使进度条不卡的情况下的最快速度。后来又尝试了两个线程:一个读取文件,一个写界面,状况依旧。
由于在process中执行的事件仍旧是在事件处理进程中执行的,因此它占用的资源太多,界面就会无法响应了,这就是根源。
那么到底有没有比较好的方法进行解决呢??
今天又再次进行了尝试,还是采用两个线程,一个读取一个写,在读之前将TextPane在界面上隐藏,然后在写线程的doInBackground方法中向其中添加内容,在完成工作后再进行显示。这样处理之后,速度比之前要快了很多,而且进度条也能正常工作了。
但这样做是否合理? Swing中说如果在非事件处理线程中对界面进行操作,有可能会导致同步问题,但有些如JTextField的SetText方法又是安全的,那么JTextPane的方法是否是线程安全的呢?