【发布时间】:2011-10-24 10:41:43
【问题描述】:
更新
我已更新此问题以包含 Java 实现的源代码,使用建议的 SwingWorker 类,以实现与 Objective-C 示例相同的结果。希望这对未来的冒险者有所帮助。
Document myDoc = ...;
Model myModel = ...;
SwingWorker analyzeDocument = new SwingWorker<Dictionary, Void>() {
@Override
public Dictionary doInBackground() {
return myDoc.analyze();
}
@Override
public void done() {
try {
stats = get();
myModel.setDict(stats);
myModel.setNeedsDisplay(true);
} catch(InterruptedException ex) {
// log
} catch(ExecutionException ex) {
// log
}
}
};
analyzeDocument.execute();
原帖
我在并发编程方面缺乏经验,我希望有人可以向我解释如何实现这一点。
在 Objective-C(使用 GCD)中,您可以执行以下操作:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
NSDictionary *stats = [myDoc analyze];
dispatch_async(dispatch_get_main_queue(), ^{
[myModel setDict:stats];
[myStatsView setNeedsDisplay:YES];
[stats release];
});
});
这段代码将在后台线程中执行[myDoc analyze],并在一个回调函数之后更新将在主线程中执行的UI。换句话说,后台线程向主线程发送一个中断,将匿名函数加入到主线程的待调用队列中。显然我不能在 Java 中使用匿名函数,但这不是重点。
我有兴趣在 Java 中为此做一些事情。我有一个Runnable 对象,它在文件系统中执行一堆东西。完成后,我想相应地更新 UI。
为了在执行此操作时不挂起主线程(即:backgroundThread.join();),我已将后台线程设置为执行回调函数以更新 UI。但这不是一个好主意,我不希望非 GUI 线程更新 GUI。
我想到的其他一些想法是轮询,但这似乎将周期抛到了窗外。根据同样的判断,使用 Futures 似乎也不是答案。这一切似乎都违背了异步操作的目的。
我唯一能想到的另一件事是使用后台线程中的SwingUtilities.invokeLater 并使用它来更新GUI。但我很好奇这将在哪个线程中执行。
也许我的看法只是扭曲了,但这似乎是一个相当大的部分要忽略。我只是想以错误的方式解决这个问题吗?
【问题讨论】:
标签: java swing concurrency swingworker runnable