The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
Let's start with a task that is very simple, but potentially time-consuming. 让我们从一个非常简单但可能耗时的任务开始。The TumbleItem applet loads a set of graphic files used in an animation. TumbleItem小程序加载动画中使用的一组图形文件。If the graphic files are loaded from an initial thread, there may be a delay before the GUI appears. 如果图形文件是从初始线程加载的,在GUI出现之前可能会有一段延迟。If the graphic files are loaded from the event dispatch thread, the GUI may be temporarily unresponsive.如果图形文件是从事件分派线程加载的,GUI可能暂时没有响应。
To avoid these problems, 为了避免这些问题,TumbleItem creates and executes an instance of SwingWorker from its initial threads. TumbleItem从其初始线程创建并执行SwingWorker的实例。The object's 对象的doInBackground method, executing in a worker thread, loads the images into an ImageIcon array, and returns a reference to it. doInBackground方法在工作线程中执行,将图像加载到ImageIcon数组中,并返回对它的引用。Then the 然后,在事件分派线程中执行的done method, executing in the event dispatch thread, invokes get to retrieve this reference, which it assigns to an applet class field named imgs. done方法调用get来检索此引用,它将此引用分配给名为imgs的小程序类字段。This allows 这允许TumbleItem to construct the GUI immediately, without waiting for the images to finish loading.TumbleItem立即构建GUI,而无需等待图像完成加载。
Here is the code that defines and executes the 下面是定义和执行SwingWorker object.SwingWorker对象的代码。
SwingWorker worker = new SwingWorker<ImageIcon[], Void>() {
@Override
public ImageIcon[] doInBackground() {
final ImageIcon[] innerImgs = new ImageIcon[nimgs];
for (int i = 0; i < nimgs; i++) {
innerImgs[i] = loadImage(i+1);
}
return innerImgs;
}
@Override
public void done() {
//Remove the "Loading images" label.
animator.removeAll();
loopslot = -1;
try {
imgs = get();
} catch (InterruptedException ignore) {}
catch (java.util.concurrent.ExecutionException e) {
String why = null;
Throwable cause = e.getCause();
if (cause != null) {
why = cause.getMessage();
} else {
why = e.getMessage();
}
System.err.println("Error retrieving file: " + why);
}
}
};All concrete subclasses of SwingWorker implement doInBackground; implementation of done is optional.SwingWorker的所有具体子类都实现doInBackground;done的实现是可选的。
Notice that 请注意,SwingWorker is a generic class, with two type parameters. SwingWorker是一个泛型类,有两个类型参数。The first type parameter specifies a return type for 第一个类型参数指定doInBackground, and also for the get method, which is invoked by other threads to retrieve the object returned by doInBackground. doInBackground和get方法的返回类型,其他线程调用该方法来检索doInBackround返回的对象。SwingWorker's second type parameter specifies a type for interim results returned while the background task is still active. SwingWorker的第二个类型参数指定后台任务仍处于活动状态时返回的临时结果的类型。Since this example doesn't return interim results, 由于本例不返回临时结果,因此Void is used as a placeholder.Void被用作占位符。
You may wonder if the code that sets 您可能会想,设置imgs is unnecessarily complicated. imgs的代码是否过于复杂。Why make 为什么让doInBackground return an object and use done to retrieve it? doInBackground返回一个对象并使用done来检索它?Why not just have 为什么不直接让doInBackground set imgs directly? doInBackground设置imgs?The problem is that the object 问题是imgs refers to is created in the worker thread and used in the event dispatch thread. imgs引用的对象是在工作线程中创建的,并在事件分派线程中使用。When objects are shared between threads in this way, you must make sure that changes made in one thread are visible to the other. 当以这种方式在线程之间共享对象时,必须确保在一个线程中所做的更改对另一个线程可见。Using 使用get guarantees this, because using get creates a happens before relationship between the code that creates imgs and the code that uses it. get可以保证这一点,因为使用get会在创建imgs的代码和使用imgs的程序之间创建一种先发生后发生的关系。For more on the happens before relationship, refer to Memory Consistency Errors in the Concurrency lesson.有关发生前关系的更多信息,请参阅并发课程中的内存一致性错误。
There are actually two ways to retrieve the object returned by 实际上有两种方法可以检索doInBackground.doInBackground返回的对象。
SwingWorker.get with no arguments. SwingWorker.get。get blocks until it is.get块,直到完成为止。SwingWorker.get with arguments indicating a timeout. SwingWorker.get。get blocks until it is — unless the timeout expires first, in which case get throws java.util.concurrent.TimeoutException.get块直到完成—除非超时首先到期,那样的话则get会抛出java.util.concurrent.TimeoutException。Be careful when invoking either overload of 从事件分派线程调用get from the event dispatch thread; until get returns, no GUI events are being processed, and the GUI is "frozen". get的重载时要小心;在get返回之前,不会处理任何GUI事件,GUI将“冻结”。Don't invoke 除非您确信后台任务已完成或接近完成,否则不要在没有参数的情况下调用get without arguments unless you are confident that the background task is complete or close to completion.get。
For more on the 有关TumbleItem example, refer to How to Use Swing Timers in the lesson Using Other Swing Features.TumbleItem示例的更多信息,请参阅使用其他Swing功能课程中的如何使用Swing计时器。