演示程序用SwingWorker()构造器在后台执行费时的操作,然后更新UI。
这个演示程序所用的SwingWorker是基于《使用SwingWorker线程》文中提出的SwingWorker类,但重新实现了它以修正一处竞态条件,添加超时支持,和改进了异常处理。
这个新的实现还基于DougLea的util.concurrent包的FutureResult类(参见“参考资料”一节)。由于大量依赖了FutureResult所做的工作,SwingWorker类的实现是简单而灵活的。
本节的余下部分更详细地描述了实现的细节,请继续往下看或直接跳到后面下载源码。
RunnableFutureResult
FutureResult,正如它的名字所暗示的,它是用来保持某动作的结果的。它被设计成和一个Callable共同使用,Callable是一个会返回结果的runnable动作:
- publicinterfaceCallable{
- Objectcall()throwsException;
- }
新的SwingWorker是一个RunnableFutureResult。在运行时,它把结果设成construct()的返回值,然后在事件派发线程中调用finished()方法。(注意:SwingWorker是一个抽象类;你要子类化它并实现construct()和finished()。)
下面的代码来自SwingWorker的run()方法:
- Callablefunction=newCallable(){
- publicObjectcall()throwsException{
- returnconstruct();
- }
- };
- RunnabledoFinished=newRunnable(){
- publicvoidrun(){
- finished();
- }
- };
- setter(function).run();
- SwingUtilities.invokeLater(doFinished);
***段把construct()转换成一个Callable动作,第二段把finished()转换成作为Runnable的doFinished。然后setter(function)被运行,doFinished被调用。
setter(function)
上面缺少的部分是setter(function)。它创建一个刻板的Runnable。在运行时,这个Runnable调用参数指定的function,然后给结果设置返回值。下面是来自FutureResult的代码:
- publicRunnablesetter(finalCallablefunction){
- returnnewRunnable(){
- publicvoidrun(){
- try{
- set(function.call());
- }
- catch(Throwableex){
- setException(ex);
- }
- }
- };
- }
注意try-catch块所作的防护。如果construct()抛出任何东西(Exception、Error等等),都会被捕捉并记录下来。
不要抢跑:先construct,再start
调用start()来启动worker线程。这是修订版的SwingWorker和原来版本的一个重要区别。
在原来的版本中,SwingWorker()构造器自动启动线程,这种做法带来了一个线程和子类构造器竞争的危险:当SwingWorker()构造器已启动了线程,而子类的构造器还没完成。弥补方法是,先构造SwingWorker,然后再调用start()。
顺便一提,RemoteTable并不调用start()。正确来说,SwingWorker是作为一个Runnable被QueuedExecutor执行的。
【编辑推荐】