Author: Hans Muller, Kathy Walrath translation: Guo Xiaogang (foosleeper@163.net)
Originally from java.sun.com
This article gives examples of using the SwingWorker class. The purpose of the SwingWorker class is to implement a background thread that allows you to perform some time-consuming operations without affecting the performance of your program's GUI. For some basic information about the SwingWorker class, see "
Thread and swing ".
Note: In September 2000 we modified this article and its examples to apply to a new version of SwingWorker class. This version of the SwingWorker class fixes some subtle thread bugs.
The thread is a basic solution to the Swing program that performs some fees or blockable operations. For example, if your application wants to send a database request or load a file according to the menu item selected by the user, then you should do this in a separate thread. This article describes the ways to complete the above work in an isolated Worker thread.
This article includes the following main contents:
SwingWorker Class: This section tells you how to download the SwingWorker class and describe the use of the SwingWorker class. Introduced the interrupt () method of the SwingWorker class. Examples of introducing a Worker thread: Demos an application that uses the SwingWorker class. Example 1: Interrupt a Swing Worker Thread: Interpret how to use the interrupt () method to interrupt the Worker thread. Example 2: Feedback from Swing Worker thread to the user: an example of an enhancement, add a mode dialog to prompt user input.
Overview: SwingWorker class
Because the SwingWorker class is not part of the Java release, you need to download and compile it to use. Its source code is here:
SwingWorker.java
SwingWorker profile
The SwingWorker class can be easily and conveniently used to calculate a value in a new thread. To use this class, you only have a SwingWorker subclass and overwrite the SwingWorker.Construct () method to perform the calculation. Then you instant it and call the start () method on this new instance.
For example, a thread is generated in the following code snippet, which constructs a string. Then, the get () method is used to obtain the value returned by the construct method before, and will wait in the case. Finally, the value of the string is displayed on the display.
SwingWorker Worker =
New swingworker () {
Public Object construct () {
Return
"Hello"
"
"World";
}
}
Worker.start ();
System.out.println (Worker.get (). TOSTRING ());
In practical applications, the constructRuct method will do more useful (but may take time). For example, it may do one of the following work:
Perform a lot of calculation execution may result in a large number of loaded code to block the network or disk I / O to block waiting for other resources
The characteristic of a SwingWorker class that is not displayed in the above code snippet is that SwingWorker allows you to perform some code in the event dispatch. You can do this by overlying the Finished () method of SwingWorker. Typically, you can use Finished () to display some components that have just been constructed or set data displayed on the component.
One limitation of the original version of the SwingWorker class is that once a Worker thread starts running, you can't interrupt it. (Translation: This article, the examples of this article and the SwingWorker class have been updated. No matter how to say, for a interactive application, let users wait until the work thread is complete. If the user wants to terminate an operation being executed, the thread that performs this should be aborted as soon as possible. Using an Interrupt () method
An interrupt () method is added to the second edition SwingWorker class to allow interrupt a thread. Your thread should be made one of the following two ways:
A thread, such as a SLEEP () or wait () method is being perrupt to throw an InterruptedException when interrupt () is called. The thread can be explicitly asked if it has been interrupted, by the following code: thread.interrupted ()
Using the working thread of the SLEEP () or wait () method (such as threads in the following example) generally does not require explicit check whether it is interrupted. It is usually made to throw an instalRuptedException in the SLEEP () or wait () method.
However, if you want to interrupt SwingWorker that does not contain timed cycles, you still need to explicitly check the interrupt with an interrupted () method.
Example of introducing a Worker thread
The remainder of this article discusses a program that contains two Worker threads. The picture below is a screenshot of the program main window, and a dialog that it pops up:
The source code of the example consists of the following files:
SwingWorker.java threadsexample.java example1.java eXample2.java
You can download a file containing all the files above.
ZIP file. In this zip file, there is also an example of an explanatory in the HTML format, and the example of this version can explain the problem (but more complicated).
Before running this example, you must compile:
/usr/local/java/jdk1.3.0/bin/javac threadsexample.java
Run this example with the following command line:
/us/local/java/jdk1.3.0/bin/java threadsexample
When you press the "START" button, the Worker thread of the corresponding example will be created. You can view its progress in your schedule. You can press the "CANCEL" button to interrupt the Worker thread. At the startup example, you will see a dialog prompt you to confirm if it is executed. Let us later in detail later.
Example 1: Interrupt Swing Worker thread
The example we want to discuss is Example1.java. The Worker thread in this example contains a loop that performs 100 times and sleeps half a second between the two cycles.
// ProgressBar Maximum Is Numloops (100) The maximum value of ProgressBar is Numloops (100)
FOR
INT i = 0; i Updatestatus (i); ... Thread.sleep (500); } In order to show you how to use the interrupt () method, our example programs allow you to launch a SwingWorker and wait for it to complete or interrupt it. The only thing for the construct () method of the SWINGWORKER subclass in the program is to call the DOWORK () method of Example1. The full source code of the DOWORK () method is listed below. This example resets the progress bar and set the label to "Interrupted" when processing the Worker thread. Since the interrupt may occur outside the SLEEP () method call, you must check the interrupt before calling the Sleep () method. Object demary () { Try { FOR INT i = 0; I IF (thread.interrupted ()) { Throw New interfacedException (); } Thread.sleep (500); } } Catch (InterruptedException E) { Updatestatus (0); Return "Interrupted"; } Return ALL DONE " } The time to perform during this method should be: Periodically let the user know that it has progressed. UpdateStatus () method will queue the runnable object for the event dispatch (remember: Do not perform the GUI work in other threads). Once the "START" button is pressed, the action listner creates SwingWorker so that the worker thread is created. After the Worker thread is started, it will execute its construct () method, which will call downork () (as shown below the code below). The following code exemplifies the subclass of SwingWorker implemented by Example1. Worker = New swingworker () { Public Object construct () { Return DOWORK (); } public Void finished () { StartButton.setenabled ( True); InterruptButton.seTenabled ( FALSE); Statusfield.Settext (Get (). TOSTRING ()); } } The Finished () method returns after the construct () method (that is, after the Worker thread is complete). Its task is just simply replacing the "start" button, and the "Cancel" button is invalid and set the value displayed by the status domain to the calculation result of the Worker. Remember that the finished () method is to execute in the event dispatch, so it can safely update the GUI directly. Example 2: Prompt from Worker Thread This example is implemented as subclass of Example1. The only difference is that after the Worker thread is executed for approximately two seconds, it will block until the user responds to a Continue / Cancel Modal dialog box. If the user chooses not "Continue", we will withdraw from the DOWORK () loop. This example demonstrates a customary method in many Worker threads: If you reach an undesired state in Worker execution, it will block up until the user is reminded or collects more information from the user with a modal dialog box. This approach is a bit complex because the display of the dialog needs to be placed in the event dispatch, and the Worker thread needs to be blocked until the user releases the mode dialog. We use Swingutilities's InvokeAit () method to pop up dialog boxes in the event dispatch. Different from invokelater (), invokeAndWait () will block it until its Runnable object returns. In our example, the runnable object is not returned until the dialog is released. We created an internal Runnable class DoshowDialog to complete the pop-up dialog. An instance variable doshowdialog.proceedconfirmed, is used to record the user's choice: Class Doshowdialog Implements runnable { Boolean proceedconfirmed; public Void Run () { Object [] options = { "Continue", "Cancel"}; INT n = joptionpane.showoptionDialog (Example2. this, "EXAMPLE2: Continue?", "EXample2", JOPTIONPANE.YES_NO_OPTION, Optionpane.question_message, NULL, Options, "Continue"); ProceedConfirmed = (n == joptionpane.yes_option); } } Because the showconfirmdialog () method pops up a modal dialog box, the call will block until the user releases the dialog. In order to display the dialog and block the call (Worker thread) until the dialog is released, the Worker thread calls the invokeAit () method to define an instance of DoshowDialog: DoshowDialog doshowdialog = New doshowdialog (); Try { Swingutilities.invokeAndwait (DoshowDialog); } Catch (java.lang.reflect. InvocationTargeTexception E) { E.PrintStackTrace (); } InvocationTargeTexception captured in the code is the residual residue of debugging DoshowDialog's Run () method. When the InvokeAndWait () method returns, the Worker thread can read DoshowDialog.ProceedConfirmed to get the user's response. We want to thank Doug Lea ("Concurrent Programming In Java", Joseph Bowbeer, and other readers who give our thread articles and SwingWorker classes. - Hans Muller and Kathy Walrath