APP下载

浅谈SwingWorker类在Java多线程开发中的应用

2020-08-14涂焱楚

科学与信息化 2020年19期

涂焱楚

摘 要 SwingWorker类是Java语言JDK中Swing包的一个类,主要用来在GUI程序中实现耗时的工作任务线程。但我们在非GUI程序的普通程序中也可使用来实现普通多线程程序,简单方便功能更强。

关键词 SwingWorker;多线程;Java

引言

在计算机系统中,进程是指程序的一次动态执行过程。程序是指令、数据及其组织形式的描述,进程则是程序运行时的实体,也是操作系统进行资源分配的基本单位。多进程操作系统支持多个进程的同时运行。线程是比进程更小的执行单位,是进程的基础之上进一步的划分,是进程中执行运算的最小单位,亦是操作系统调度运行的基本单位。线程和进程一样,也是实现并发的一个基本单位。所谓多线程是指一个进程在执行过程中可以产生多个更小的程序单元,也即是线程,这些线程同时存在,同时运行。可以说,多线程在较低的层次上扩展了多任务的概念,但是与进程相比较,线程更轻量级,创建、撤销一个线程比启动一个新进程的开销要小得多。进程和线程在现在的主流操作系统中都得到了较好的支持。在实际应用中,多线程非常有用,Java语言很早就对多线程程序的开发提供支持。

1 在Java中使用多线程的一般方式

Java语言中很早就实现了对多线程编程的支持。目前,Java中实现多线程编程的方式流行的主要有两种,一种是继承Thread 类,另一种是实现 Runnable 接口。其中通过继承 Thread 类创建线程,存在的一个局限就是不能多继承了。所以很多资料都推荐采用实现 Runnable 接口的方式。需要说明的是,这两种方式在工作时的性质都是一样的,并没有本质的区别。它们都要通过实现run()方法来完成线程的基本任务,调用Thread类的start()方法来启动线程。另外,这两种方式实现的线程执行完后都不能简单方便地返回执行的结果[1]。

2 SwingWorker类的原始用途

SwingWork类是Java的Swing包中的一个类。Swing包在Java语言中主要是用来支持进行图形界面(GUI)程序的开发的。但是,Swing包中的类并不都是线程安全的,如果使用不当会使得程序的图形界面反应迟钝;所以,从Java SE6开始引入SwingWorker类来改善Swing程序的结构,提高界面的灵活性。

在Swing实现的图形用户界面程序中,把不同的任务分别由两个不同的线程来实现;一个是事件分发线程(EDT),另一个是任务线程。程序中图形用户界面的绘制和更新、用户输入或各种事件的响应,都放在EDT中实现,耗时的任务和I/O密集型操作则放在任务线程中实现。这样可以有效地提高程序的响应性能,给用户更好的使用体验。SwingWorker类就是用来实现这个任务线程的。SwingWorker类的设计里,已经贴心地提供了多个方法供用户重载选用,它们互相配合,和事件分发线程密切沟通,实现多方面的功能。SwingWorker是一个抽象类,支持泛型。我们可以从它继承来实现任务线程。它的原型为SwingWorker< T,V>,其中T,V为两个泛型参数,T是doInBackground和get方法的返回类型,也就是线程执行结果的返回类型;V是线程中间结果的返回类型,在GUI程序中可以用来展示任务的执行进度。我们重载其中的doInBackground()方法来完成基本任务,调用execute()方法来启动任务线程。线程执行完后调用get()方法可以取得最后的返回结果[2]。

3 SwingWorker类在一般多线程编程中的使用

SwingWorker类由于原始设计的用途是在Swing开发的GUI程序中配合EDT线程实现任务线程,而GUI程序在Java程序的开发中比重并不大,所以一般Java编程的教材资料中对这个类的介绍比较少。偶有介绍,也都是就其本意来谈。其实,在不涉及图形用户界面的情况下,SwingWorker类一样可以用于编制普通多线程程序,有些时候比继承Thread类或是实现Runnable接口更方便,可以提供更强的功能。

利用SwingWorker类编制普通的多线程程序其实十分简单:

首先,我们定义一个类,继承自SwingWorker;类中重载doInBackground()方法实现线程的基本功能。就像继承Thread类时或是實现Runnable接口的实现run()方法一样。

其次,调用SwingWorker类中的Execute()方法来启动这个线程,类似调用Thread类start()方法来启动线程。

不过利用SwingWorker类来实现多线程,能也就是方便实现其他的一些功能。第一,线程运行结束后,也就是doInBackground()方法运行完后,可以返回一个执行的结果。我们通过调用SwingWorker类的get()方法获得线程的返回结果值。由于结果是必须在线程执行完后才有,所以我们随时都可以调用SwingWorker类的isDone()方法来判断线程是否结束。其次,我们还可以让线程在运行时不断返回一些中间结果值,这个需要push()方法和process()方法的配合,我们可以在doInBackground()方法中调用push()方法返回中间结果,重载process()来处理或利用中间结果实现某些功能。最后,我们甚至可以在线程运行时取消线程的执行。

另外,需要注意的是SwingWorker实例不可复用,每次执行任务必须生成新的实例。

4 结束语

SwingWorker类不但可以在利用Swing编制的GUI程序中实现任务线程,在非GUI程序中也可以用来实现普通多线程,而且提供很多方便实用的功能。

参考文献

[1] [美]Cay S.Horstmann,周立新、陈波.Java核心技术 卷I:基础知识(原书第10版)[M].北京:机械工业出版社,2016:277.

[2] [美]Herbert Schidt,孙鸿飞.Java 11官方参考手册(第11版)[M].北京:清华大学出版社,2020:196.