涂焱楚


摘 要 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.