`

Swing的第一推动力(转载)

阅读更多
转载自[url]http://blog.sina.com.cn/swingjava [/url]

Swing通过AWT的事件循环系统来推动整个系统的运行,这个AWT的事件系统就是Swing系统的这个“第一推动力”。

不像一般GUI系统事件循环是由单个线程完成的,Swing事件循环实际上存在两个线程。具体到Windows上来说,一个线程叫AWT- Windows,它负责从操作系统获取底层事件,并将事件处理后翻译成Swing能懂的事件,并放入到Swing的系统事件队列(EventQueue) 中;另一个线程叫EventQueue-0,该线程就是所谓的EDT(Event Dispatch Thread),它负责从事件队列中获取事件,并分派到Swing组件中,最终产生有意义的动作事件传递给组件事件处理器。有时EDT还负责将事件队列中的事件进行预处理,比如多个连续的Paint事件合并成一个等等。下图是Swing事件处理系统的示意图:


和一般GUI工具系统不同,Swing的这种双事件处理线程有其设计目的。总的来说这种事件处理线程模型增加了Swing图形系统的灵活性和可扩展性,为Swing实现高级的功能预留下了扩展空间。

Swing著名的"灰框(gray rect)"问题就是利用这种巧妙结构实现的。单单就EDT的模型来说,Swing存在普通GUI系统常见的线程占用问题。所谓的"灰框"问题是指,某些 Swing程序由于编写较差,将长时间任务放在EDT上进行。如果此时恰巧有一个窗口遮住了Swing程序,当用户移开覆盖窗口时,由于任务阻塞了 EDT,使Paint事件得不到及时处理,造成Swing界面出现灰色方框的现象。

JDK 1.6采用了如下方法解决了这个问题:当被遮挡的窗口被暴露时,AWT-Windows线程获得到了这个EXPOSE事件,在将事件翻译成Paint事件给事件队列之前,AWT-Windows先从操作系统的图形缓冲里获取窗口被遮挡前的图像(注意某些Linux图形系统并不支持这种缓冲,所以Swing 在某些Linux系统上并没有解决这个问题),然后将这个图像采用bltbit的方法画在暴露出的灰框上,然后才把Paint事件发送给Swing事件队列。这儿的关键就在于获取底层事件的线程AWT-Windows同Swing的EDT不是一个线程,因此EDT虽然被长时间任务阻塞了,但是AWT- Windows这个线程并没有被阻塞。因此可以及时的处理窗口暴露事件,避免了灰框问题。

由于Swing程序在被别的窗口遮住时,其状态可能已经发生了变化,因此bltbit缓冲的图像往往同当前的窗口状态不能同步。如果你留心观察就会发现这个现象:窗口被移开的瞬间,虽然没有问题,但是图像是被遮盖前的,之后不久窗口会发生突然的变化,将当前正确的窗口画出来。这时的更新是Swing程序在完成了长时间任务后,处理Paint事件重画当前窗口造成的。

其实这种双线程结构还有许多其他的应用。Java2D性能的大幅度提高,其中就利用了这种双线程结构。EDT在处理多个Graphics2D原子动作事件时,先进行了合理的预处理,比如动作合并,动作数据集成,批处理模式的发送给图形卡等等。

Swing的问题问题从本质上来说任何图形系统都会存在。不知你听说过SWT对应的白框问题没有,这个问题和Swing的在本质上是一样的,只是SWT窗口缺省的背景是白色。SWT由于其单线程事件处理模型,就很难解决这个问题。

同样在Solaris和Linux,Swing的事件处理线程都是两个,只不过其他平台上叫AWT-Solaris或者AWT-Linux线程罢了。有了这些AWT-xxx事件循环线程对Swing事件队列提供的原始动力,整个Swing机器就开始了运转。这就是Swing的第一推动力。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics