对于我能读到的内容,它用于在swing应用程序中调度新线程以执行某些“后台”工作,但是使用它而不是“普通”线程有什么好处?
使用新线程是不是一样,完成时使用SwingUtilities.invokeLater调用一些GUI方法?...
我在这里缺少什么?
http://en.wikipedia.org/wiki/SwingWorker
http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html
答案 0 :(得分:10)
是的,你可以完成SwingWorker对vanilla线程+ invokeLater的处理。 SwingWorker提供了一种可预测的集成方式,可以在后台线程上完成任务并在EDT上报告结果。 SwingWorker还增加了对中间结果的支持。同样,您可以自己完成所有这些,但有时可以轻松使用集成且可预测的解决方案,尤其是在并发方面。
答案 1 :(得分:3)
代码示例:
import org.jdesktop.swingx.util.SwingWorker; // This one is from swingx
// another one is built in
// since JDK 1.6 AFAIK?
public class SwingWorkerTest {
public static void main( String[] args ) {
/**
* First method
*/
new Thread() {
public void run() {
/** Do work that would freeze GUI here */
final Object result = new Object();
java.awt.EventQueue.invokeLater( new Runnable() {
public void run() {
/** Update GUI here */
}
} );
}
}.start();
/**
* Second method
*/
new SwingWorker< Object , Object >() {
protected Object doInBackground() throws Exception {
/** Do work that would freeze GUI here */
return null;
}
protected void done() {
try {
Object result = get();
/** Update GUI here */
}
catch ( Exception ex ) {
ex.printStackTrace();
if ( ex instanceof java.lang.InterruptedException )
return;
}
}
}.execute();
}
}
选择总是取决于个人偏好和用例。
第二种方法在重构时具有优势。
当你使用的方法太大时,你可以更容易地将匿名类转换为内部类。我个人的偏好是第二个,因为我们已经建立了一个框架,可以添加SwingWorkers并一个接一个地执行......
答案 2 :(得分:2)
SwingWorker是一种常见模式的实现(在.Net中我读过 GuiWorker BackgroundWorker),你必须在GUI程序中做一些工作,但要保持GUI响应。问题是GUI库通常不是多线程安全的,因此实现这些工作程序的常用方法是使用库的消息循环将消息传输到应用程序的事件循环中。
这些类允许您轻松更新GUI。通常,它们有一个update(int status)
方法,由线程调用,由类调度,并由GUI处理,而线程继续工作。
使用普通线程,您需要为此任务编写自己的事件或其他一些消息传递机制,如果您经常需要此功能,这可能会很麻烦。例如,在Java中使用invokeLater,您可以将用于更新gui的代码混合到用于执行工作的代码中。 SwingWorker允许您将事物分开。
答案 3 :(得分:1)
回答你的问题,你没有遗漏任何东西。这个类只是一个方便的实用程序,用于包装您描述的功能(启动另一个线程来执行后台工作,然后在结果上调用EDT上的一些最终操作)。
答案 4 :(得分:1)
使用Swing时,重要的是要知道主摆动处理(即渲染)发生在单个线程(不是你的主线程)上。这通常称为Swing或awt事件线程。那些熟悉JDK pre 1.6的人会记住“灰色矩形”错误,如果你在一个事件调度员花了太多时间用于挥杆组件。这是什么意思。在任何swing应用程序中,您将运行2个线程,您现在必须处理它们。通常情况下,如果事件调度程序中的所有操作(单击按钮时被解雇的代码)很短(即更改siwng按钮的状态),则可以在事件调度程序内部运行此操作。如果您的应用程序要调用Web服务或数据库,或者您的应用程序状态是由外部事件(即jms)驱动的,或者您希望只是使您的UI更具交互性(即构建项目列表并且能够做其他的事情)你应该使用awt事件线程以外的线程(主要的摆动线程)。因此,在这些情况下,您会生成一个新线程并执行您必须执行的操作,并且当结果最终返回时,您必须以某种方式创建一个可由awt / swing调度程序执行的事件。 SwingWorker是一个很棒的小设计模式,允许你这样做(另一种方式是SwingUtilities)。它对于从外部源获取数据或进行长时间计算(渲染图形场景)特别有用。它有助于自动调度和后续重新集成来自外部线程(除了awt线程)的结果。对于异步事件(即来自JMS的事件需要更新结果,请使用SwingUtilities)。
答案 5 :(得分:0)
SwingWorker
使得简单的示例代码更加简洁。然而,它创造了一个泥球。与GUI和执行逻辑的通信都焊接在一起。所以,我不希望在实际的生产代码中看到它。
答案 6 :(得分:0)
SwingWorker比使用自己的线程更容易,因为它为您提供了两件令人痛苦的事情,UI和后台进程之间的线程协调以及有效的循环,后台工作继续工作并将更新发送回UI递增,如处理大量数据或加载大型列表。缺点(或优势)取决于您如何看待它,它隐藏了底层实现,因此未来版本可能具有不同的行为,性能等,这可能是不合需要的。我发现它作为UI事件和我自己的命令代码之间的粘合剂非常有用,SwingWorker维护了UI的链接,我的代码泵送了数据。