全,
我们在应用程序中加载数据时遇到了问题。当前实现的目的是具有用于数据加载的异步机制。
我基本上想知道这方面是否有任何好的模式或实践。
应用程序有许多不同的UI组件,它们都不是以标准方式编码的。所有这些都是由配置(即xml)生成的。数据加载是通过单击日历触发的,日历将向数据加载器发送异步消息,其中大约有6个实例(属于同一类)将从数据库加载数据。一旦加载和处理了数据,数据加载器类将异步地将表数据发送到要在其中显示的JTable。
由于数据加载的时间可以从每秒到1到2分钟不等,因此需要一个进度对话框。在开始/完成数据加载时,还编写了一个额外的类来侦听数据加载程序中的事件。当任何数据加载程序开始加载时,都会显示一个对话框,指示数据正在加载。当最后一次数据加载器完成时,应该隐藏对话框。
当前问题/问题
有两个问题发生:
我们已经尝试了添加花式关键字周围的显示和隐藏方法的进展,但仍然得到类似的发布。我认为可能需要进行某种重写,但我想进一步了解异步java模式。这一机制需要更加有力和可靠。
电流处理
如果你对我们目前的进程感兴趣,我试着总结一下下面的事件。这可能会对设计/实现中的问题有所帮助。
任何帮助都将不胜感激。如果我错过了什么,那么请补充意见,我会更新问题。
谢谢,
安迪兹
发布于 2012-01-12 16:20:58
我查了一下SwingWorker。我研究了这些例子,但我的想法是从SwingWorker中派生出每个SwingWorker--我想。
我决定不这样做,并发现DataLoadDialog类和Swing JDialog之间交互的方式存在问题。我把我的例子简化得太多了。另外还有两个组合也触发了数据加载。一个组合体将强制3个数据加载器开始加载,另一个组合用于另3个数据加载器。这将迫使我添加额外的配置,这将是尴尬的,因为系统是写的方式。
我最初尝试将同步关键字添加到loadStart和loadComplete中,但它们仍然没有修复这个问题。我还在显示/隐藏对话框的位置设置了invokeAndWait。我希望这样可以防止多个线程试图显示/隐藏进度--但它没有。我用invokeAndWait替换了invokeLater,这似乎很有效。
我完全同意SwingWorker的观点,像这样的场景应该更多地放在设计上--我们在这里做得很差--这是我讨厌的。整个并发解决方案是在同步加载初始数据大约20分钟后组合在一起的--1个加载器依次从数据库检索数据。加载的数据量是相当可怕的--而且它还必须经过某种条件调整。
安迪兹
发布于 2012-01-07 14:39:56
这些问题听起来像是违反了基本Swing规则:所有组件访问都必须发生在EDT上。确保在EDT上触发所有用户反馈(显示/隐藏对话框、更新进程状态、更新表数据)。
帮助这样做的一个有用的类是SwingWorker,它的api文档非常广泛,并且有如何直接访问模型/组件的示例。
一些伪代码片段展示了如何通过propertyChangeEvent传递中间数据,从而将工作人员与实际ui稍微分离开来:
// on user click (here we are on EDT),
// open the dialog, create the loader, add a PropertyChangeListener and start
showProcessDialog();
MySwingWorker worker = new MySwingWorker();
PropertyChangeListener l = new PropertyChangeListener() {
public void propertyChanged(....) {
if (StateValue.DONE == evt.getNewValue) {
closeProcessDialog();
}
if ("chunkAvailable".equals(evt.getPropertyName()) {
addChunkToTable((ChunkType) evt.getNewValue());
}
}
}
worker.addPropertyChangeListener(l);
worker.execute();
// custom implementation of SwingWorker
public MySwingWorker extends SwingWorker<ResultType, ChunkType> {
@Override
protected <ResultType> doInBackground() {
// here we are in the worker thread
// start the actual loaders
Dataloaders loaders = ....
// process their result/s
ResultType endResult = ...;
while (...) {
ChunkType intermediateResult = ....
// possibly produce some end result
endResult = ...
// publish the intermediate chunk
publish(intermediateResult);
}
return endResult;
}
@Override
protected void process(List<ChunkType> chunks) {
// here we are on the EDT, so it's safe to either notify swing listener
// or access swing components/models directly (as shown in the api/tutorial example)
for(ChunkType chunk: chunks) {
PropertyChangeEvent e = new PropertyChangeEvent(this, "chunkAvailable", null, chunk);
getPropertyChangeSupport().firePropertyChange(e);
}
}
}https://stackoverflow.com/questions/8758213
复制相似问题